You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于16位硬件时间戳的溢出处理及连续时间向量生成优化

解决16位时间戳溢出问题,生成连续时间向量

我用的硬件输出16位时间戳,最低有效位是50微秒,单量程约3.25秒。现在要把这些时间戳转成量程更大的连续时间向量,但处理溢出时总觉得现有代码不够严谨,而且我是Swift新手,对字节级操作不太熟。

现有代码的问题

当前实现逻辑绕,硬写了魔法数字,还有强制解包的风险,容易出问题:

let timeVectorRaw: [UInt16] = <time values>

// First timestamp will not necessarily be zero, so need to record the value of the first entry which will be subtracted later so the time vector starts at zero
timeOffsetInt = Int(timeVectorRaw[0])
// Last timestamp (Uint16) (not scaled/no offset)
var lastRawValue: UInt16 = 0

var lastWholeNumberValue: Int = 0

for timeValue in timeVectorRaw {
    // if time vector is empty or if timestamp hasn't overflowed yet, no adjustment necessary
    if timeVectorWrapped.isEmpty || timeVectorWrapped.last! < timeValue {
        timeVectorWrapped.append(Int(timeValue))
    }
    else if timeValue < lastRawValue {
        // Essentially floor(last time value / Uint16 max value)
        lastWholeNumberValue = timeVectorWrapped.last! + 65536 - ((timeVectorWrapped.last!) % 65536)
        timeVectorWrapped.append(Int(timeValue) + lastWholeNumberValue)

    }
    else {
        timeVectorWrapped.append(Int(timeValue) + lastWholeNumberValue)
    }
    lastRawValue = timeValue
}

for timeValueWrap in timeVectorWrapped {
    // subtract offset and multiply by scale factor (50us/lsb)
    timeVector.append(Float((timeValueWrap - timeOffsetInt)) * 0.000050)
}

优化后的实现

用溢出计数的方式处理更直观,代码也更严谨,适合Swift新手理解:

// 定义常量,避免魔法数字,提升可读性
let microsecondsPerLSB: Double = 50
let uInt16Range = Int(UInt16.max) + 1 // 65536,UInt16的总取值数

let timeVectorRaw: [UInt16] = <time values>
var timeVector: [Double] = []

// 处理空数组的边界情况,避免崩溃
guard !timeVectorRaw.isEmpty else {
    print("时间戳数组为空")
    return
}

// 基准偏移量,让时间向量从0开始
let baseOffset = Int(timeVectorRaw[0])
var overflowCount = 0
var previousRawValue = timeVectorRaw[0]

// 遍历计算包裹后的时间值
var wrappedTimes: [Int] = [baseOffset]
for currentRaw in timeVectorRaw.dropFirst() {
    // 判断是否溢出:当前值比上一个小,说明翻过了UInt16的最大值
    if currentRaw < previousRawValue {
        overflowCount += 1
    }
    // 计算实际的累计时间值
    let wrappedTime = Int(currentRaw) + overflowCount * uInt16Range
    wrappedTimes.append(wrappedTime)
    // 更新上一个值
    previousRawValue = currentRaw
}

// 转换为实际时间(秒),并减去基准偏移量
timeVector = wrappedTimes.map { wrappedTime in
    let relativeTicks = wrappedTime - baseOffset
    return Double(relativeTicks) * microsecondsPerLSB / 1_000_000
}

关键逻辑说明

  1. 溢出判断:当当前时间戳currentRaw小于上一个值previousRawValue,说明硬件的16位计数器从65535溢出回0了,此时溢出计数加1。
  2. 包裹时间计算:每次溢出相当于额外增加了一个完整的UInt16量程(65536个刻度),所以实际时间值是当前刻度值加上溢出次数 × 65536。
  3. 时间转换:减去基准偏移量让时间从0开始,再把刻度数转成秒(50微秒/刻度 = 50×10^-6秒/刻度)。
  4. 安全处理:用guard判断空数组,避免强制解包,代码更稳健。

内容的提问来源于stack exchange,提问作者awk_leg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 03:33:27