2017-01-21 27 views
1

В настоящее время я проверяю онлайн-курс edX о встроенных системах и узнаю об использовании таймера SysTick для расчета прошедшего времени.Использование ARM Cortex SysTick для расчета истекшего времени; что произойдет, когда счетчик SysTick перевернется?

Picture of logic I'm referring to

Code of logic I'm referring to

Однако есть один момент, который сбивает с толку меня. Я понимаю идею вычитания «сейчас» из «последней», чтобы получить прошедшее время. Тем не менее, что вы делаете, когда «сейчас» перевернется, когда таймер SysTick достигает 0 и получает перезагрузку, но «последним» является значение от ПЕРЕД прежде чем таймер SysTick перевернулся (так «сейчас» есть> чем «последний», когда обычно это должно быть меньше)? Значение хранится в unsigned long, так же как это нарушает программу? Или это никогда не произойдет, и если да, то почему? Буду признателен за любую помощь по расчистке!

Я посмотрел на единственную ссылку, которую я мог найти, которая была похожа на мой вопрос здесь: How to deal with a wrapping counter in embedded C, но я не нашел ясного ответа на мой вопрос.

+0

Почему бы вам просто не попробовать какие-то значения? 'unsigned' integer wraparound очень хорошо определен, и даже если счетчик обертывает, * целочисленная разность * знака * до предыдущего значения будет по-прежнему правильной (если она достаточно мала, т. е. половина вашего диапазона' int') – tofro

+0

[Использование модульная арифметика, чтобы избежать проблем с переполнением]] (https://blogs.msdn.microsoft.com/oldnewthing/20050531-22/?p=35493) – kkrambo

+0

@tofro Я дам ему шанс, спасибо! Я просто хотел прояснить, что происходит логически заблаговременно, так как я решил реализовать код без полного понимания логики, было бы бессмысленно. – Yuerno

ответ

1

Возьмите 3 разрядный счетчик, все масштабируется равно 24 или 32 (я думаю, что SysTick таймеры 24.

Так подсчет вверх или вниз не имеет значения, вам просто нужно правильно настроить операнды. Так сказать, обратный отсчет 7,6,5,4 7 -. 4 3 отсчетов но как насчет 1,0,7,6 в двоичном 1 - 6 = 001 - 110

 1 
    001 
+ 001 
======= 

и решить ее

011 
    001 
+ 001 
======= 
    011  

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

Должно быть простым в написании программы для 4 или 5-битного счетчика, попробуйте случайные величины. Или использовать фиксированный размер счетчиков позволяющих пролонгировать с помощью простых чисел

#include <stdio.h> 
#define BITMASK 0xF 
int main (void) 
{ 
    unsigned int now; 
    unsigned int beg; 
    unsigned int end; 
    unsigned int ra; 
    unsigned int rb; 
    now=0; 
    for(ra=0;ra<100000;ra++) 
    { 
     beg=now; 
     for(rb=0;rb<13;rb++) now--; 
     end=now; 
     if(((beg-now)&BITMASK)!=13) 
     { 
      printf("Error 0x%X 0x%X\n",beg,end); 
     } 
    } 
    printf("Done.\n"); 
    return(1); 
} 

это работает только, если это счетчик, который перекатывается от всех нулей до всех единиц или всех из них до всех нулей в зависимости от направления. Я бы надеялся, что это станет очевидным, если вы установите гипотетический 3-битный таймер, чтобы начать с 5, и он перевернулся с нуля обратно на 5 заданных значений, тогда три шага могут быть 1,0,5,4 и 1-4 не 3

111 
    001 
+ 011 
========= 
    101 

другой способ думать об этом еще одна особенность дополнения до двух, вблизи точки панорамного

101 -3 
110 -2 
111 -1 
000 +0 
001 +1 
010 +2 

это так же, как номер строки, мы использовали в начальной школе. Из битовой диаграммы 110 до 010 составляет 4 шага +2 -2 -2 или 4 единицы на числовой строке. В основном, используя красоту двухкомпонентных дополнений, и мы знаем, что сложение и вычитание в двоичном формате благодаря дополнению двух компонентов не являются неподписанными или подписанными, одни и те же битовые шаблоны приводят к тем же битовым шаблонам. Именно так мы их интерпретируем. Поэтому мы немного обманываем, принимая подписанную математику и интерпретируем результат как неподписанный.

+0

вы должны знать размер своего счетчика, поэтому, если у вас есть системный счетчик, который является 24-битным счетчиком, вы не можете просто использовать 32-битную математику, результат будет неправильным, вы должны замаскировать результат с помощью 24-битной маски. Вы можете использовать меньшую маску 20 бит или 16 или что угодно, если в пределах того количества бит, которое счетчик перескакивает со всех нулей ко всем или всем из них ко всем нулям. для счетчиков/таймеров, подобных этим, в общем случае это означает, что счетчик вниз, который вы перезагружаете для всех, является счетчиком вверх для всех нулей (при опрокидывании) –

+0

, очевидно, что он не работает, если счетчик дважды свертывается, так что вам либо нужно следить за ним, чтобы рулон и добавление этих опрокидываний в результат или обеспечение того, чтобы вы пробовали достаточно быстро, чтобы никогда не позволять ему проходить отсчет начала или даже слишком близко. возьмите пример программы выше, и вместо цикла, запускаемого до 13, пусть он будет работать до 17 или 19, и сравнить разницу с 17 или 19. должно быть довольно очевидно с маской 15, которую вы никогда не сможете получить. –

+0

Это очень полезно, спасибо за то, что разработали его с примерами! Вопрос о битовой маске: если вы делаете операции вычитания, не будет ли результат в конечном итоге быть 24 битами все время, так что дополнительные биты, прошедшие 24, останутся 0 независимо от того, что? Как 32-битная математика влияет на то, что вы используете только 24 бита? – Yuerno

1

old_timer был фантастический ответ, и после делать некоторые дополнительные исследования моего собственного, я нашел еще один большой ответ на переполнение стека, который я полагал, что я связала бы так: How to subtract two unsigned ints with wrap around or overflow

+0

Да! Ответ очень прост, все, что вам нужно сделать, это вычесть из счетчика катания, чтобы получить прошедшее время, вычитание обернется вокруг надежным. Завернутый таймер содержит значение 0x05, в то время как прошедшее время равно 0xF5, если вы оцениваете 0x05 - 0xF0, ответ по-прежнему равен 0x10 или 16. 16 единиц времени истек, обертывание агностик. –

1

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

В этом случае SysTick является 24-битный счетчик так:

uint32_t start_time = getSystick() ; 

// do something 

uint32_t end_time = getSystick() ; 

uint32_t elapsed_time_in_systicks = ((start_time << 8) - (end_time << 8)) >> 8 ; 

Обратите внимание на порядок операндов - SysTick подсчитывает вниз. Это предполагает, что вы устанавливаете максимальное значение перезагрузки 0xffffff, и этот сист не переносится более одного раза.

Если временные интервалы таковы, что счетчик может обернуть более одного раза, тогда вам может не понадобиться такое высокое разрешение и, возможно, возможно использовать меньшее значение перезагрузки и обработчик прерываний, который увеличивает счетчик и использует это более низкое разрешение счетчик для измерения времени.

В качестве альтернативы вы можете использовать счетчик uint8_t, умноженный на прерывание перезагрузки. Затем этот счетчик можно объединить с 24 битами для создания подлинного 32-битного счетчика. Однако необходимо соблюдать осторожность, чтобы обеспечить согласованность - чтобы вы не совмещали систему непосредственно перед ее перезагрузкой с помощью счетчика перезагрузки сразу после (или наоборот). Это можно сделать следующим образом:

uint32_t getSystick32() 
{ 
    uint8_t msb ; 
    uint32_t systick ; 
    do 
    { 
     msb = getSystickReloadCounter() ; 
     systick = getSystick() ; 

    } while(msb != systick_reload_counter) ; 

    return msb << 24 | systick ; 
} 
+0

Спасибо за ответ! Это интересный способ сделать это. – Yuerno

 Смежные вопросы

  • Нет связанных вопросов^_^