2017-01-06 12 views
1

Я работаю над маленьким 32-разрядным микроконтроллером без FPU. Мне нужен способ конвертировать счетчик 100 МГц, чтобы быть правильными миллисекундами.Математика с фиксированной точкой для преобразования счетчика 100 МГц в миллисекунду

Я хочу создать функцию, которая вернет мне текущее время в миллисекундах.

static uint32_t prev_time; 
static uint32_t time; 
uint32_t get_current_time() 
{ 
    curr_time = get_100MHz_counter_value(); 
    uint32_t elapsed_time = curr_time - prev_time; 

    prev_time = curr_time; 
    time = /* DONT KNOW HOW TO CONVERT THE TIME USING FIXED POINT MATH */ 
    return time; 
} 
+1

Разделить на 100000? Уверен, у вас есть деление – immibis

+0

100MHz = 100000000 циклов в секунду. Как сказал immibis, разделите на 100000 за миллисекунды. Вам не нужна математика с плавающей запятой, целые числа будут работать нормально. – MateoConLechuga

+0

деления очень дороги в конструкции микроконтроллеров. – Godspped

ответ

0

Предполагая, что процессор может перемножить два 32 разрядных целых чисел без знака в результате чего 64 бит продукта в (может быть внутренним для умножения), вы можете использовать эту волшебную формулу число разделить на 100000 (100000 == 32 * 3125).

n/100000 = ((n>>5)*175921861ull)>>(32+7) // ull = unsigned long long 

Последовательность умножения (п >> 5) 175921861, а затем взять верхний 32 бит продукта и сдвиг вправо 7 бит, чтобы получить фактор.

Некоторые процессоры имеют инструкцию для умножения двух 32-битных чисел и получения верхних 32 бит 64-битного продукта с именем команды, аналогичным umulh.

+0

Начальный (n >> 5) кажется, что вы ненужно бросаете точность. Почему бы не умножить на ((2^32)/10000) -1), а затем сдвинуть вниз на 32? –

+0

@RussSchultz - Цель состоит в том, чтобы эмулировать целочисленное деление n/100000, которое усекает: quotient = floor (n/100000). Так как это усекающее деление, n/100000 = n/(32 * 3125) = (n >> 5)/3125. В качестве еще одного примера усечения целочисленного деления рассмотрим 31/8 == (31 >> 1)/4 == ((31 >> 1) >> 1)/2 == ((31 >> 1) >> 1) >> 1 = 3. При усечении это не имеет значения, чем 31/8 = 3,875 и ((31 >> 1) >> 1) >> 1 = 3,5, дробная часть удаляется путем усечения и никогда не приводит к результатам в округлении. – rcgldr

+0

@RussSchultz - Посмотрите на эту предыдущую тему о [магических числах] (http://stackoverflow.com/questions/41183935/why-does-gcc-use-multiplication-by-a-strange-number-in-implementing целочисленная-диви/41224096 # 41224096). Для n/100000 предварительный сдвиг == 5. Сначала выполняется предварительный сдвиг, поэтому модифицированный делитель = 3125. Начальное значение ℓ = ceil (log2 (3215) = 12. Начальный диапазон для 33-битного умножителя m: (2^(32 + 12))/3125 <= m <= (2^(32 + 12) + 2^12)/3125, пост-сдвиг = 12, а множитель оптимизирован до (2^(32 + 7))/3125) + 1 = умножитель 28 бит 175921861, post shift = 7 – rcgldr

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

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