Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.65/23: Рейтинг темы: голосов - 23, средняя оценка - 4.65
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
1

Проблемы с подсчетом времени

04.04.2016, 11:28. Просмотров 4200. Ответов 16
Метки нет (Все метки)

Добрый день!
Реализвал не хитрый код - счетчика милисекунд
Код
uint32_t T1=0;
uint32_t T2=0;

ISR(TIMER0_COMPA_vect)
{
ms++;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}

int main(void)
{

while(1)
{
T1=ms;
T2=ms;
uint32_t T3=T2-T1;
}
}
Иногда начал проскакывать неправильный подсчет времени! Залез я в дизассемблер и увидел следующее, что для операции m++, T2=ms и T3=T2-T1 используются те же регистры, что в определенный момент может наложится и я получу значение, не то что нужно:

Код
   ms++;
0000003D  LDS R24,0x0110      Load direct from data sposi
0000003F  LDS R25,0x0111      Load direct from data sposi
00000041  LDS R26,0x0112      Load direct from data sposi
00000043  LDS R27,0x0113      Load direct from data sposi
00000045  ADIW R24,0x01      Add immediate to word
00000046  ADC R26,R1      Add wyth carry
00000047  ADC R27,R1      Add wyth carry
00000048  STS 0x0110,R24      Store direct to data sposi
0000004A  STS 0x0111,R25      Store direct to data sposi
0000004C  STS 0x0112,R26      Store direct to data sposi
0000004E  STS 0x0113,R27      Store direct to data sposi
asm("nop");
00000050  NOP       No operation
asm("nop");
00000051  NOP       No operation
asm("nop");
00000052  NOP       No operation
asm("nop");
00000053  NOP       No operation
}

T1=ms;
00000445  STS 0x0104,R20      Store direct to data sposi
00000447  STS 0x0105,R21      Store direct to data sposi
00000449  STS 0x0106,R22      Store direct to data sposi
0000044B  STS 0x0107,R23      Store direct to data sposi
T2=ms;
0000044E  LDS R24,0x0110      Load direct from data sposi
00000450  LDS R25,0x0111      Load direct from data sposi
00000452  LDS R26,0x0112      Load direct from data sposi
00000454  LDS R27,0x0113      Load direct from data sposi
00000456  STS 0x0100,R24      Store direct to data sposi
00000458  STS 0x0101,R25      Store direct to data sposi
0000045A  STS 0x0102,R26      Store direct to data sposi
0000045C  STS 0x0103,R27      Store direct to data sposi
Подскажите как уйти от этой проблемы? Может у меня подход не правильный? Думал запрет прерывания ставить, но в дальнейшем запрос времени будет использоваться постоянно и везде ставить запрет, будет вносить погрешность!
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.04.2016, 11:28
Ответы с готовыми решениями:

задачка с подсчетом времени
Добрый день. Смысл задачи вот в чем. Есть страничка я делаю запрос через curl и мне приходит ответ...

Запрос по сортировке с подсчетом ср. времени
Есть база данных - на картинке. Нужно вывести среднее время от производства до реализации, те от...

Сортировка методом вставок с подсчетом времени
Мне нужна Сортировка методом вставок написанная для массива и листа с подсчетом времени. Никто не...

Файловый менеджер с подсчетом времени звучания в текущей директории муз файлов
Удалось найти реализацию начала файлового менеджера. Он показывает корни жесткого диска, в корень...

Расчет времени пуска,установившегося времени,времени торможения и паузу для лифта
t0=(3600/h)*(1-E) - пауза.ЕЕ можно взять произвольно(самим). А остальное надо высчитывать....

16
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
04.04.2016, 11:37 2
В обработчике прерываний вначале надо сохранять все используемые регистры, а по выходу восстанавливать.
0
Bytt
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
04.04.2016, 11:53 3
Цитата Сообщение от u37
В обработчике прерываний вначале надо сохранять все используемые регистры, а по выходу восстанавливать.
Объявлено же явно - ISR (процедура обработки прерываний). Компилятор должен все сделать сам.
0
u37
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,113
04.04.2016, 12:03 4
Bytt, вопрос был - " для операции m++, T2=ms и T3=T2-T1 используются те же регистры, что в определенный момент может наложится"
0
04.04.2016, 12:03
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
04.04.2016, 12:08 5
Где объявление ms? Она volatile?
В общем,
1. Объявить ms как volatile.
2. Либо запрещать прерывания на время чтения ms (в atomic.h есть всякие удобные вещи для этого), либо считывать её в цикле, пока два раза подряд не получите одинаковое значение (суть проблемы: вы можете прочитать один-два-три байта ms, потом придёт прерывание, значение изменится - и вуаля: было 0x000000FF, вы прочитали младший байт, пришло прерывание - значение стало 0x00000100, прочитали остальные байты - и получили 0x000001FF).

А что те же регистры - проблема компилятора, не ваша. push/pop никто не отменял - посмотрите листинг за пределами процитированного вами фрагмента.
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 12:11 6
Цитата Сообщение от oomomstir
Где объявление ms? Она volatile?
В общем,
1. Объявить ms как volatile.
2. Либо запрещать прерывания на время чтения ms (в atomic.h есть всякие удобные вещи для этого), либо считывать её в цикле, пока два раза подряд не получите одинаковое значение (суть проблемы: вы можете прочитать один-два-три байта ms, потом придёт прерывание, значение изменится - и вуаля: было 0x000000FF, вы прочитали младший байт, пришло прерывание - значение стало 0x00000100, прочитали остальные байты - и получили 0x000001FF).

А что те же регистры - проблема компилятора, не ваша. push/pop никто не отменял - посмотрите листинг за пределами процитированного вами фрагмента.
Ок! Спасибо! Попробую что-то с этим сделать.
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 12:21 7
А что касается чтения значений то да, получил T1=24316 и T2=24060! Не думаю, что volatile тут поможет! Возможно, только запрет прерывания! Кстати при работе с Arduino такого вопроса не возникало? (не могу найти в каком файле описана функция myttys() и прерывания TIMER0 - может кто знает, подскажете!)

команды PUSH действительно есть перед m++, и если они сохраняют значения регистров, то я тогда вообще не понимаю в какой момент происход неправильное чтение!
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
04.04.2016, 12:34 8
MorkTwys, wiring.c - там просто прерывания запрещают.
А неправильное - то, что я вам описал. Один байт из прошлого значения счётчика, остальные из следующего. Хотя числа у вас немного странные - 0x5EFC и 0x5DFC, можно подумать, что в процессе считывания пришло аж 4 прерывания таймера...
0
ShodS
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
04.04.2016, 12:45 9
Цитата Сообщение от MorkTwys
то я тогда вообще не понимаю в какой момент происход неправильное чтение!
Несколько раз уже намекают поставить запрет прерывания в чтении переменной...
Но как говорится лучше один раз увидеть чем много раз услышать )))
Код
int main(void)
{

while(1)
{
cli ();
T1=ms;
T2=ms;
sei ();
uint32_t T3=T2-T1;
}
}
0
div
0 / 0 / 0
Регистрация: 26.01.2009
Сообщений: 3
04.04.2016, 13:02 10
Не-а:

Код
int main(void)
{

while(1)
{
cli ();
T1=ms;
sei ();
cli ();
T2=ms;
sei ();
uint32_t T3=T2-T1;
}
}
0
HotD
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
04.04.2016, 13:15 11
налицо нарушение атомарности. Запрещайте прерывания, когда читаете/пишете переменную, которая используется в прерывании.
0
omtomtubo
0 / 0 / 0
Регистрация: 23.03.2012
Сообщений: 1,017
04.04.2016, 13:34 12
А на какой частоте контроллер работает?
И для чего 4 nop-а в прерывании?

А вообще, мне кажется, что нужно по-другому использовать периферию.
Можете задачу объяснить?
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 14:00 13
Цитата Сообщение от omtomtubo
А на какой частоте контроллер работает?
И для чего 4 nop-а в прерывании?

А вообще, мне кажется, что нужно по-другому использовать периферию.
Можете задачу объяснить?
F_CPU=14746500UL

Выполение множества подзадач, каждая из которых должна выполнятся со своим промежутком времени!
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 14:04 14
Цитата Сообщение от ShodS
Цитата Сообщение от MorkTwys
то я тогда вообще не понимаю в какой момент происход неправильное чтение!
Несколько раз уже намекают поставить запрет прерывания в чтении переменной...
Но как говорится лучше один раз увидеть чем много раз услышать )))
Код
int main(void)
{

while(1)
{
cli ();
T1=ms;
T2=ms;
sei ();
uint32_t T3=T2-T1;
}
}
Это я понимаю, но если я буду считывать значение переменной ms в 100х местах программы, мне надо везде запрертить прерывания! А если задача будет касатся точного подсчета времени у меня будут погрешности!
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 14:08 15
Наверное правельным решением будет написать функцию с запрещением прерываний и возвратом значения ms
0
MorkTwys
0 / 0 / 0
Регистрация: 07.02.2016
Сообщений: 124
04.04.2016, 14:09 16
Цитата Сообщение от oomomstir
MorkTwys, wiring.c - там просто прерывания запрещают.
А неправильное - то, что я вам описал. Один байт из прошлого значения счётчика, остальные из следующего. Хотя числа у вас немного странные - 0x5EFC и 0x5DFC, можно подумать, что в процессе считывания пришло аж 4 прерывания таймера...
Спасибо! Нашел!
0
Редиски
0 / 0 / 0
Регистрация: 28.03.2014
Сообщений: 103
04.04.2016, 19:42 17
А в CVAVR volatile можно писать один раз, при объявлении переменной, или надо каждый раз прописывать? В разных источникак по разному указывают
0
04.04.2016, 19:42
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.04.2016, 19:42

Сортировка подсчетом
Дан список из N (N≤2*10⁵) элементов, которые принимают целые значения от 0 до 100. Отсортируйте...

программа с подсчетом
всем привет.помогите с циклом пожалуйста.вот кусок программы import java.util.Scanner; ...

Сортировка подсчетом
Помогите понять, что означают переменные min и max. пример в нете нашел. Сортировка подсчетом ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.