簡體   English   中英

划分由16位和32位變量組成的48位數字

[英]Divide a 48-bit number which is composed of a 16bit and a 32bit variable

我正在開發用於嵌入式微控制器(STN1110)的軟件。 它沒有FPU或SFP仿真。

有一個SDK方法可返回控制器的正常運行時間(以微秒為單位),分為兩個變量:uint16(msw)和uint32(lsw)。

我想將此“對”轉換為具有秒精度( / 1000 / 1000 1000/1000)的單個uint32。

SDK API文檔規定以下內容:

uint32 TimeGet48 (uint16 * time_msw)
-----------------------------------------   
Read the current full 48-bit system time.

Returns all 48 bits of the current value of the system's 1MHz clock. The resolution of the returned 32 bit value is one microsecond, with the most significant word returned through the pointer passed as a parameter. The clock therefore wraps after approximately 8.9 years. That should be enough for most purposes.

Parameters:
- time_msw: A pointer to store the most significant word of the current system time
Returns:
- Lower 32 bits to the current system time.

這里的主要問題是,控制器最多僅支持uint32 ,因此不支持uint64

我“粘合”了一些我認為可能是解決方案的代碼。 並非如此,因為uint16值> 0時就會出現錯誤,而我找不到它。

uint32 divide(uint32 time_in_us_lsb, uint16 time_in_us_msb, uint32 divisor)
{
    uint32 value1 = (uint32)time_in_us_msb & 0xFFFF;
    uint32 value2 = (uint32)(time_in_us_lsb >> 16) & 0xFFFF;
    uint32 value3 = (uint32)time_in_us_lsb & 0xFFFF;

    value2 += (value1 % divisor) << 16;
    value3 += (value2 % divisor) << 16;

    return (((value2 / divisor) << 16) & 0xFFFF0000) | ( value3 / divisor);
}

uint32 getUptimeSeconds() {
    uint32 time_in_us_lsb;
    uint16 time_in_us_msb;

    time_in_us_lsb = TimeGet48(&time_in_us_msb);   
    uint32 result = divide(time_in_us_lsb, time_in_us_msb, 100000);

    time_in_us_lsb = (uint32)result & 0xFFFFFFFF;
    time_in_us_msb = 0;

    return divide(time_in_us_lsb, time_in_us_msb, 10); 
}

注意:這里速度不是問題,因為在應用程序生存期內不會經常調用該函數。

編輯:添加了uint32功能限制。

..一旦uint16值> 0,就會出現錯誤,而我找不到它。

在“控制器正常運行時間(以微秒為單位)”中給出至少一個錯誤

// uint32 result = divide(time_in_ms_lsb, time_in_ms_msb, 100000);
uint32 result    = divide(time_in_ms_lsb, time_in_ms_msb, 1000000);

僅僅使用uint64_t更有意義。

uint32 divide(uint32 time_in_ms_lsb, uint16 time_in_ms_msb, uint32 divisor) {
  uint64_t sum = ((uint64_t)time_in_ms_msb << 32) | divisor;
  return (uint32)(sum / divisor);
}

推薦:在代碼中使用ms毫秒數看起來像毫秒 建議us使用“μSeconds”。

給定您定位的CPU,您可能需要針對固定除數對其進行優化。 您的情況除以1000000。

為此,您可以使用a / 1000000 = a *(2 ^ 64/1000000)/ 2 ^ 64。 (2 ^ 64/1000000)不是整數,但是一個近似值就足夠了。 乘法可以通過一系列移位和加法來完成。 您可以對(2 ^ 64/1000000)添加一些錯誤,以減少移位和增加。 結果將略有下降,但不會太大。

正確完成后,正確答案的結果將不超過1。 如果那很重要,則可以再次將結果乘以1000000,進行比較,然后根據需要將結果調整為1。

注意:在上面的近似中,您不必使用2 ^ 64。 嘗試2 ^ 32或2 ^ 48或其他數字,看看是否能減少移位和增加次數。

PS:檢查編譯器的作用是(a * uint64_t(1<<48 / 1000000)) >> 48

應該:

uint32 getUptimeSeconds() {
    uint32 time_in_us_lsb;
    uint16 time_in_us_msb;

    time_in_us_lsb = TimeGet48(&time_in_us_msb);   
    uint32 result = divide(time_in_us_lsb, time_in_us_msb, 10000);

    time_in_us_lsb = (uint32)result & 0xFFFFFFFF;
    time_in_us_msb = 0;

    return divide(time_in_us_lsb, time_in_us_msb, 100); 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM