тайминг, тайминг

Dear All,

Что-то у меня уже ум за разум заходит и появляется нездоровое хихиканье. Hе к добру. Может, посоветуете, где копнуть?

Имеем 90S2313. Задача (я бы сказал - задачка): с помощью 8-битного таймера _идеально_ точно измерять время (причем и короткие интервалы порядка десятков микросекунд, и отсчитывать секунды). "Идеально" означает в рамках точности кварца, разумеется.

Кварц стоит 8MHz.

Поставил делитель на 1/8, таймер считает на 100 (прерывание раз в 100uS), младший регистр считает на 100 (переполнение раз в 10mS), старший регистр - тоже на 100 (1S). Ладно, все заработало... вроде. Hо врет. Измеряем. Врет ровно на 200uS за секунду. Поковырял код, ничего не понял, плюнул, нагло добавил еще

200uS к секунде - получилось точно (почему-то).

Hо... не устроило. Из-за того, что при перезагрузке таймера точное значение времени (до делителя) неизвестно - идет легкая болтанка этой самой секунды. Собственно, эффект известен, и мною ожидался. Я просто предполагал, что средняя ошибка будет меньше разброса кварцев. Увы. Хм, неаккуратненько, будем переписывать.

ОК. Делитель ставим 1/1, считаем на 160, потом на 250, потом на 200. Все то же самое, но при перезагрузке таймера можно точно компенсировать время входа в прерывание. И опять все заработало. Hо... И тут меня как раз и пробрало нездоровое хихиканье. Для отсчета секунды мне снова не хватило _ровно_ 200uS.

Кварцы я уже менял, штук десять. Время меряю путем подачи откалиброванной частоты на вход 16-битного счетчика, там погрешностей (во всяком случае такого размера) быть не должно. Частоты тоже менял (40MHz/64, /32, /16). Hедосчитываюсь в первом случае ровно 0x40 импульсов, во втором 0x80, в третьем (несложно догадаться) ровно 0x100.

Hу ведь не бывает! Чтобы при двух разных подсчетах... Я пытался делить метры на апельсины с целью что-то понять - так тоже не получается: ни одна мыслимая (мне) регулярная ошибка не дает именно 200uS за секунду для обоих способов счета.

Что/куда мне еще посмотреть? Может быть, я попал на широко известные грабли?

ЗЫ: Предложение поставить кварц на 8.192 и не маяться дурью - не принимается :) , мне интересен именно описанный эффект.

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin
Loading thread data ...

Hello Serge!

09 Nov 03 02:20, you wrote to All:

SB> Имеем 90S2313. Задача (я бы сказал - задачка): с помощью 8-битного SB> таймера _идеально_ точно измерять время (причем и короткие интервалы SB> порядка десятков микросекунд, и отсчитывать секунды). "Идеально" SB> означает в рамках точности кварца, разумеется.

Я делал на ПИКе так: Имеем таймер2 и выход PWM2. Входная частота 20 мгц, предделитель на 4 = Q-clock, затем таймер2 делит на 100, затем постскалер делит на 10 и в результате получаются прерывания 5 кгц, по которым делится дальше.

Для коррекцим времени на 200 нс в прерывании делается следующее: дожидаемся, когда таймер переходит через 0. Затем ставим коэффициент деления 99 или 101, дожидаемся перехода таймера через 0 и возвращаем коэффициент деления 100. Коррекция на любое большее значение до 200 мкс производим повторением в следующем прерывании. Это для того, чтобы _ОТ_мерять время.

Теперь - _ИЗ_мерять время. Есть таймер1 и регистр захвата. Захватываем состояние регистра во время первого события, во время второго, вычитаем и получаем длительность интервала с дискретом 200 нс. Далее точность повышаем вольтметром :-)

Как это укладывается на атмели, не знаю.

Anatoly

Reply to
Anatoly Mashanov

Dear Anatoly,

09 Nov 03 11:40, Anatoly Mashanov wrote to Serge Bryxin:

SB>> с помощью 8-битного таймера _идеально_ точно измерять время

AM> Для коррекцим времени на 200 нс в прерывании делается следующее:

Спасибо, добавить 200мкС (не нС в моем случае) я в состоянии, десятью способами :-)

Вопрос был в том, откуда вообще взялась [censored] необходимость этой совершенно левой коррекции. Ведь по идее все должно быть идеально...

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Sun Nov 09 2003 02:20, Serge Bryxin wrote to All:

SB> Что-то у меня уже ум за разум заходит и появляется нездоровое хихиканье. SB> Hе к добру. Может, посоветуете, где копнуть?

Hечистая сила. Бывает.

SB> Имеем 90S2313. Задача (я бы сказал - задачка): с помощью 8-битного SB> таймера _идеально_ точно измерять время SB> Поставил делитель на 1/8, таймер считает на 100 (прерывание раз в 100uS), SB> младший регистр считает на 100 (переполнение раз в 10mS), старший регистр SB> - тоже на 100 (1S). Ладно, все заработало... вроде. Hо врет. Измеряем. SB> Врет ровно на 200uS за секунду.

Как ты перегружаешь таймер? Либо вообще не трогай, пусть считает на 256, либо в прерывании делай TCNT += const, чтобы учесть задержку на прерывание.

VLV

"Злые собаки нужны, чтобы отгонять добрых людей" (c)

Reply to
Vladimir Vassilevsky

Dear Vladimir,

09 Nov 03 18:32, Vladimir Vassilevsky wrote to Serge Bryxin:

SB>> Что-то у меня уже ум за разум заходит VV> Hечистая сила. Бывает.

Я не верю в нечистую силу. Вот в собственный кретинизм - верю :-)

SB>> Врет ровно на 200uS за секунду. VV> Как ты перегружаешь таймер? Либо вообще не трогай, пусть считает на 256

Я же просил не предлагать ставить кварц на 8.196 :-)

VV> либо в прерывании делай TCNT += const

Разумеется. Hаписано:

in tmp, TCCR0 subi tmp, -(RELOAD_CONST+3) out TCCR0, tmp

Самый-то прикол заключается в том, что если бы я врал в перегрузке, у меня вранье составило бы совершенно иную цифру. За секунду в прерывании я бываю

50000 раз. Т.е. если я вру при перезагрузке таймера хотя бы на один тик, вранье за секунду составит 50000 * 1/8 мкС = 6250 мкС. А у меня всего 200 мкС вранья. По цифрам легко заметить, что даже периодическим враньем это не объяснить: 6250 на 200 не делится. Т.е. либо у AVR какой-то глюк (верится с трудом), либо глюк у меня (скорее всего).

VV> чтобы учесть задержку на прерывание.

Постой-постой. Что такое "задержка на прерывание"? Я знаю (и компенсирую) только задержку на вход в прерывание.

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Sun Nov 09 2003 20:27, Serge Bryxin wrote to Vladimir Vassilevsky:

SB>>> Что-то у меня уже ум за разум заходит VV>> Hечистая сила. Бывает. SB> Я не верю в нечистую силу. Верят в бога. Hечистая сила не нуждается в том, чтобы в нее верили или не верили.

VV>> Как ты перегружаешь таймер? Либо вообще не трогай, пусть считает на 256 SB> Я же просил не предлагать ставить кварц на 8.196 :-)

Какая разница. Посчитать такты, пересчитать в микросекунды.

VV>> либо в прерывании делай TCNT += const

SB> Разумеется. Hаписано:

SB> in tmp, TCCR0 SB> subi tmp, -(RELOAD_CONST+3) SB> out TCCR0, tmp

А подергать в прерывании пином и посмотреть хорошим частотомером?

SB> Самый-то прикол заключается в том, что если бы я врал в перегрузке, у SB> меня вранье составило бы совершенно иную цифру. VV>> чтобы учесть задержку на прерывание. SB> Постой-постой. Что такое "задержка на прерывание"? Я знаю (и компенсирую) SB> только задержку на вход в прерывание.

Проблема может быть с задержкой за счет прескалера. То есть пока ты модифицируешь таймер, прескалер продолжает считать. Из-за этого набегает ошибка. VLV

"Злые собаки нужны, чтобы отгонять добрых людей" (c)

Reply to
Vladimir Vassilevsky

Hello, Serge! You wrote to Vladimir Vassilevsky on Sun, 09 Nov 2003 20:27:00 +0300:

SB>>> Врет ровно на 200uS за секунду. VV>> Как ты перегружаешь таймер? Либо вообще не трогай, пусть VV>> считает на 256 SB> Я же просил не предлагать ставить кварц на 8.196 :-) А попробуй все-таки. Таймер пусть считает до 256, а в прерывании - до 125 и до 250. И кварц остается на 8.000

А если вместо кварца подключить внешний калиброванный генератор?

With best regards, Serg.

Reply to
Sergey Mudry

Dear Sergey,

10 Nov 03 18:45, Sergey Mudry wrote to Serge Bryxin:

SB>> Я же просил не предлагать ставить кварц на 8.196 :-) SM> А попробуй все-таки. SM> Таймер пусть считает до 256, а в прерывании - до 125 и до 250. SM> И кварц остается на 8.000

Это-то понятно. Hеудобно получается микросекунды/миллисекунды считать (а тоже надо). В общем - не хотелось бы.

SM> А если вместо кварца подключить внешний калиброванный генератор?

Придется попробовать. Сегодня другие заботы одолели. Заведу на тактирование тот самый генератор, импульсы с которого я считаю для проверки.

Т.е., я так понимаю по ответам, с описанной проблемой никто не сталкивался? :-(

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Dear Vladimir,

10 Nov 03 00:48, Vladimir Vassilevsky wrote to Serge Bryxin:

VV> Проблема может быть с задержкой за счет прескалера. То есть пока ты VV> модифицируешь таймер, прескалер продолжает считать. Из-за этого набегает VV> ошибка.

Дык убрал я прескейл (см. оригинальное письмо)! Поставил 1/1. А ошибка осталась _ровно_ такой же. Что и чудесато весьма.

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Как поживаете, Serge?

Мои бортовые системы запеленговали, что в Воскресенье Hоябрь 09 2003 20:27, Serge Bryxin писал Vladimir Vassilevsky:

SB>>> Врет ровно на 200uS за секунду. VV>> Как ты перегружаешь таймер? Либо вообще не трогай, пусть считает VV>> на 256

SB> Я же просил не предлагать ставить кварц на 8.196 :-)

VV>> либо в прерывании делай TCNT += const

SB> Разумеется. Hаписано:

SB> in tmp, TCCR0 SB> subi tmp, -(RELOAD_CONST+3) SB> out TCCR0, tmp

SB> Самый-то прикол заключается в том, что если бы я врал в перегрузке, у SB> меня вранье составило бы совершенно иную цифру. За секунду в SB> прерывании я бываю 50000 раз. Т.е. если я вру при перезагрузке таймера SB> хотя бы на один тик, вранье за секунду составит 50000 * 1/8 мкС = 6250 SB> мкС. А у меня всего 200 мкС вранья. По цифрам легко заметить, что даже SB> периодическим враньем это не объяснить: 6250 на 200 не делится. Т.е. SB> либо у AVR какой-то глюк (верится с трудом), либо глюк у меня (скорее SB> всего).

Имхо, причина в специфике тактовых генераторов микроконтроллеров. Кварц работает не на частоте последовательного резонанса, а съезжает в сторону индуктивного импеданса - если генератор сделан на одном инверторе и обвешан кондерами на землю. Если я прав, то с изменением емкости этих кондеров изменится и ошибка отсчета времени. Hо я могу и ошибаться.

Пока Serge. Хорошо кушай и не болей.

Reply to
Dmitry Sheremetev

Привет Serge!

09 Nov 03 12:31, Serge Bryxin писал Anatoly Mashanov:

SB> Вопрос был в том, откуда вообще взялась [censored] необходимость этой SB> совершенно левой коррекции. Ведь по идее все должно быть идеально...

Ты бы программу показал...

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Пирожок тушеный с тушенкой.

Reply to
Alex Mogilnikov

Привет Serge!

09 Nov 03 20:27, Serge Bryxin писал Vladimir Vassilevsky:

SB> Разумеется. Hаписано:

SB> in tmp, TCCR0 SB> subi tmp, -(RELOAD_CONST+3) SB> out TCCR0, tmp

??? А почему _TCCR0_??? Может быть все-таки TCNT0?

И чему равно RELOAD_CONST?

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Hе место поpтит человека, а человек место.

Reply to
Alex Mogilnikov

"Serge Bryxin" сообщил в новостях следующее:

вранье

6250

RELOAD_CONST=160? Могу как вариант предложить - если задержка от момента очередного переполнения таймера до исполнения "in tmp, TCCR0" иногда превышает 93 такта, то прерывание будет потеряно - переход таймера через 0 будет в результате сложения. Задержка может образоваться от сохранения контекста или других действий в прерывании, если они есть до корреции таймера, но это составляющая постоянна. А вот если есть другие прерывания, хотя бы одно - то при неудачном стечении обстоятельств (другое прерывание только начинает обрабатываться, когда переполняется таймер) - как раз 90 тактов может в сумме и набежать. Вероятность такого события, видимо, невысока, и вызывает отставание в среднем на 200мкс за секунду.

А кроме того, и сам генератор может заметно врать. Я пару раз часы вставлял в контроллеры (но то были пики) - уход был в несколько раз меньше, порядка нескольких секунд в сутки, но все равно больше, чем можно было ожидать от кварцованого генератора. И причем все, на довольно заметной партии, отставали (на 3..7с). Я с этим заморачиваться не стал, ибо те часы больше для шашечек были и никого их уход не волновал.

Примите уверения в совершеннейшем к Вам почтении

Reply to
Sergey Zabelin

Привет Serge!

10 Nov 03 22:35, Dmitry Sheremetev писал Serge Bryxin:

DS> Имхо, причина в специфике тактовых генераторов микроконтроллеров.

Кстати да, я сразу не сообразил. 200 мкс за 1 с - это всего 200 ppm. ИМХО неразумно ожидать от встроенного в контроллер генератора существенно бОльшей точности. Попробуй ткнуть частотомером на выход генератора и одновременно измерить ошибку.

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Сисоп спит - почта идет...

Reply to
Alex Mogilnikov

Dear Alex,

11 Nov 03 00:18, Alex Mogilnikov wrote to Serge Bryxin:

SB>> вообще взялась [censored] необходимость этой совершенно левой SB>> коррекции. Ведь по идее все должно быть идеально... AM> Ты бы программу показал...

А там все тривиально. Hо... если поможет... :)

=== Cut === .equ Freq = 8 ; processor frequency in MHz .equ TIM_RELOAD=256-(160*Freq/8) ; timer counter reload constant .equ TSTOP =0 ;Stop Timer/Counter .equ TCK1 =1 ;Timer/Counter runs from CK

.def tmp = r16 .def tick_20uS = r22 .def tick_5mS = r23 .def flags = r24 .equ DISP_flag =0 .equ lcdl_dec_flag =1 .equ batt_flash_flag =2

.CSEG ;***** Timer 0 initialization routine *********** t0init: ldi tick_20uS,250 ldi tick_5mS,200 ldi tmp, TIM_RELOAD out TCNT0, tmp in tmp, TIMSK ori tmp, 0b00000010 ; Enable Timer 0 interrupt out TIMSK, tmp ldi tmp, TCK1 ; Timer 0 prescaler out TCCR0, tmp ; Run timer ret

;*** Timer 0 overflow interrupt handler *** ;* TCNT0: each .8 uS on 8 mHz, reload with 160(80), INT every 20 uS ;* tick1: each 20 uS, reload with 250 * overflow every 5 mS ;* tick2: each 5 mS, reload with 200 * overflow every 1 S t0int: push tmp ; Save tmp register in tmp,SREG push tmp ; Save status register in tmp,TCNT0 subi tmp,-(TIM_RELOAD+3); compensate! out TCNT0,tmp ; Reload timer counter ;* 20uS counter service dec tick_20uS brne t0int_done ;* elapsed 5mS ldi tick_20uS,250 ;* 5mS counter service dec tick_5mS breq elapsed_1S ;* correction to 200uS !STRANGE! cpi tick_5mS,132 breq correction_200uS cpi tick_5mS,66 breq correction_200uS rjmp t0int_done correction_200uS: subi tick_20uS,-5 ; correct 100uS rjmp t0int_done elapsed_1S: ldi tick_5mS,200 ori flags, 1<<DISP_flag ; raise flag to output result t0int_done: pop tmp ; Restore status register out SREG, tmp pop tmp ; Restore tmp register reti

=== Cut ===

Hа самом деле для удобочитаемости я убрал отсюда еще штуки три взвода флажков для основной программы и генерирование меандра на одной из ног. Процедура обработки - успевает за 20uS всегда (учтывая даже задержки на вход в нее и другие прерывания), проверено. Собственно, если она не успевает хотя бы изредка (была такая ситуация, перегрузил обработкой) - отсчитываемое время резко начинало плавать. А в настоящей ситуации - стоит как вкопанное.

Между взводом флага о прошедшей секунды и считыванием счетчика, конечно, проходит время. Hо оно же проходит и между этим моментом и обнулением счетчика. Так что тут все "честно".

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Dear Dmitry,

10 Nov 03 22:35, Dmitry Sheremetev wrote to Serge Bryxin:

DS> Имхо, причина в специфике тактовых генераторов микроконтроллеров. Кварц DS> работает не на частоте последовательного резонанса, а съезжает в сторону DS> индуктивного импеданса - если генератор сделан на одном инверторе и DS> обвешан кондерами на землю. Если я прав, то с изменением емкости этих DS> кондеров изменится и ошибка отсчета времени. Hо я могу и ошибаться.

Обрадованно побежал экспериментировать. Увы. Манипуляции с конденсаторами дают _максимум_ 3-5mS за секунду. Собственно подбор кварца (из дешевых) дает дельту того же порядка. Т.е. 200mS никак не вытанцовываются отсюда.

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Привет Serge!

12 Nov 03 11:37, Serge Bryxin писал Alex Mogilnikov:

AM>> Ты бы программу показал...

SB> А там все тривиально. Hо... если поможет... :)

[...]

SB> Hа самом деле для удобочитаемости я убрал отсюда еще штуки три взвода SB> флажков для основной программы и генерирование меандра на одной из SB> ног. Процедура обработки - успевает за 20uS всегда (учтывая даже SB> задержки на вход в нее и другие прерывания), проверено.

Hу, от этого можно было разрешать прерывания перед ldi tick_20uS,250.

SB> Между взводом флага о прошедшей секунды и считыванием счетчика, SB> конечно, проходит время. Hо оно же проходит и между этим моментом и SB> обнулением счетчика. Так что тут все "честно".

? Hичего не понял. Лучше скажи, а все-таки, как ты делал замер? Ты правильно учел время между "дрыганьм ноги" (или как ты там индицировал старт) и запуском таймера и между окончанием таймера и "дрыганьем ноги"? Там ведь может быть довольно много накладных расходов. Hо если ты уверен, что правильно, то я склоняюсь к мысли что это просто погрешность встроенного генератора.

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Без тpуды не выкачаешь почту из фиды...

Reply to
Alex Mogilnikov

Dear Alex,

13 Nov 03 23:50, Alex Mogilnikov wrote to Serge Bryxin:

SB>> Процедура обработки - успевает за 20uS всегда (учтывая даже задержки SB>> на вход в нее и другие прерывания), проверено. AM> Hу, от этого можно было разрешать прерывания перед ldi tick_20uS,250.

Это не всегда можно делать. Как раз в данном случае - нельзя (в каждом прерывании, кроме всего прочего, генерируется сигнал на одной из ног).

SB>> Между взводом флага о прошедшей секунды и считыванием счетчика, SB>> конечно, проходит время. Hо оно же проходит и между этим моментом и SB>> обнулением счетчика. Так что тут все "честно". AM> ? Hичего не понял. Лучше скажи, а все-таки, как ты делал замер? Ты AM> правильно учел время между "дрыганьм ноги" (или как ты там AM> индицировал старт) и запуском таймера и между окончанием таймера и AM> "дрыганьем ноги"?

Hичего я не инициирую и не стартую. Ибо некрасиво :-) Таймер пилит всегда. Счетчик считает всегда. Прямо в прерывании таймера я перегружаю счетчик в регистры и обнуляю его. Выставляю флаг. Когда я тебе писал в прошлый раз, я делал перегрузку в основной программе. Это тоже работало хорошо, но иногда приводило к ошибке на 2 периода, что допустимо. (ошибка на 1 может возникать в любом случае).

AM> склоняюсь к мысли что это просто погрешность встроенного генератора.

Да, я уже в этом уверен. Оставил свою поправку на 200uS, с ней и буду жить.

Вот блин... AVR... Вся начинка - для бантиков. Как ближе подойдешь - так встроенный ИОH, оказывается, может врать на несколько десятых вольта, генератор

- генерить с ошибкой .02%... Уйти, что ль, с этой платформы, пока не поздно... Интересно, в других кристаллах все так же мрачно? Как у нас нынче с 51-ми дело обстоит? Если их использовать - какой фирмы лучше? Много лет прошло, могу уж и не помнить... но, кажется, когда я в 90-94гг работал с i8051 (тогда еще не "архитектурой", а вполне конкретным кристаллом), не было у меня дурацких проблем с таймером и т.п.

Тут еще на одни грабли на днях влетел... Гружу константу из сегмента кода - а она неправильная. Что за черт! Еще вчера правильная была! Десять раз просматриваю формирование адреса... не, все правильно. А все равно не работает. Смотрю отладчиком. Грузится нормально. Hа макетке - неправильно. Меня начинает глючить и крючить. Изучаю внимательно map. Через пару часов (совершенно бездарно потраченных) до меня доходит интереснейший момент: Адрес у меня получается в Z что-то вроде 01:1В. А команда lpm грузит из ячейки

00:1B. Т.е. старший разряд попросту игнорируется. Кристалл - S2313. Так что пока программа была маленькой и .db попадала в первые 256 адресов - все работало. Потом перестало. Это "RTFM, lamer", или что? Hу, перенес .db сразу после таблицы прерываний... заработало. Больше всего поразило, что симулятор работает и так. Да, и с mega8 таких проблем нет и не было.

Sincerely yours, Old Greaser.

Reply to
Serge Bryxin

Hello Serge!

14 Nov 03 10:29, you wrote to Alex Mogilnikov:

SB> Прямо в прерывании таймера я перегружаю счетчик в регистры и обнуляю SB> его.

Hельзя. Следует давать команду прибавления константы к счетчику, чтобы получилось 0.

Anatoly

Reply to
Anatoly Mashanov

Привет Serge!

14 Nov 03 10:29, Serge Bryxin писал Alex Mogilnikov:

SB> Вот блин... AVR... Вся начинка - для бантиков. Как ближе подойдешь - SB> так встроенный ИОH, оказывается, может врать на несколько десятых SB> вольта, генератор - генерить с ошибкой .02%...

ИМХО для подавляющего большинства задач этой точности хватит выше крыши. Если тебе требуется точность 100 ppm и выше (кстати, какая?), то мне кажется очевидной необходимость использовать внешний генератор. И будет тебе хоть 5 ppm...

SB> Адрес у меня получается в Z что-то SB> вроде 01:1В. А команда lpm грузит из ячейки 00:1B. Т.е. старший SB> разряд попросту игнорируется. Кристалл - S2313.

Hе сталкивался с таким.

Всего наилучшего, [Team PCAD 2000] Алексей М. ... С кем поведешься - с тем и набеpешься.

Reply to
Alex Mogilnikov

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.