1

我在一些 eeprom 上有一个 56 字节的寄存器可用,我想用它来存储引擎小时数。目前我只使用 3 个字节来增加一个 60 秒的计时器,然后下载信息(这个数字在传输前很少超过 9999 分钟)。

问题是我需要将日期与此相关联。每次车辆启动时,我都需要开始记录我的小时数,但我需要确定该小时是从哪个小时开始增加的。

因此,如果我有一个 byte[56] 数组,那么存储日期(或仅一个小时的日期)后跟一个数字并能够区分它们的最简单方法是什么?

对于传输,我需要一种方法来遍历数组并提取日期或小时,以及小时数。

对此的任何想法都会很棒,非常感谢。

报告的最终结果类似于:

06:00 - 38 分钟 09:00 - 60 分钟 10:00 - 60 分钟等

4

2 回答 2

1

好的,这是一个将您需要的所有数据放入 56 个字节的方案的想法(事实上,我们最多可以将 11 个日期和时间放入 56 个字节):

假设您不希望这个系统持续超过一千年,我们可以将一年的第一部分定义为,即 2013 年分为两部分,纪元和年份。

  • 纪元:5 位(或一个字节),允许 0-31
  • 年份:7 位(或一个字节),允许 0-99
  • 日:9 位(两个字节),允许 0-365
  • 小时:5 位(一个字节),允许 0-24
  • 第二:12bits(两个字节)允许0-3600

现在您可以简单地使用 7 个字节并增加每个字节的值,并允许您存储多达 8 个日期和时间,但是您可以创建一个结构并位爆炸各个位以进一步压缩它,从而允许您将其塞进 40 位(或 5 个字节)让你有 11 个日期。

如果你真的是死记硬背,你也可以放弃时代,但上述方案将允许你使用高达 3199 的日期。

我相信还有其他更紧凑的方法,即自 01.01.1970 以来的毫秒数到未来几年可能会减少几位,但会减少代码的寿命,但我没有看过实际值。

一些示例代码(已更新为使用 BitArray,因为 bool 在内部是一个字节(?!)但 BitArray 实际上是位......在 OPS 情况下非常重要。:

OP 应该注意,我相信您想要存储每小时驾驶的分钟数,但这将需要更多的空间(他们每小时开车的记录或每天的开始和停止记录,表明他们开始和停止的分钟(毕竟必须在开始之后停止)。下面的代码将允许您记录在给定的一天中已经驾驶了多少分钟。

using System;
using System.Collections;

namespace BitBangingDate
{
    class Program
    {
        static void Main(string[] args)
        {
            CompactDateManipulator x = new CompactDateManipulator();
            Console.WriteLine(x.ToString());
            x.Month = 7;
            x.Day = 27;
            x.Minute = 1234;
            Console.WriteLine(x.ToString());

            var bitArr = x.GetCompactedArray();

            CompactDateManipulator x1 = new CompactDateManipulator();//create new blank date to test whether can be reiitialised from BitArray

            x1.ReinitialiseDateFromBitArray(bitArr);

            Console.WriteLine(x1.ToString());
        }
    }

    class CompactDateManipulator
    {
        CompactDate _date = new CompactDate();

        public int Month
        {
            get
            {
                return BoolArrayToInt(_date.month);
            }
            set
            {
                IntToBoolArray(ref _date.month, value);
            }
        }
        public int Day
        {
            get
            {
                return BoolArrayToInt(_date.day);
            }
            set
            {
                IntToBoolArray(ref _date.day, value);
            }
        }
        public int Minute
        {
            get
            {
                return BoolArrayToInt(_date.minute);
            }
            set
            {
                IntToBoolArray(ref _date.minute, value);
            }
        }

        public BitArray GetCompactedArray()
        {
            return _date.GetFullArray();
        }

        public void ReinitialiseDateFromBitArray(BitArray arr)
        {
            _date.SetDate(arr);
        }

        //utility methods
        void IntToBoolArray(ref bool[] bits, int input)
        {
            var len = bits.Length;
            for (int i = 0; i < len; i++)
            {
                bits[i] = (input & 1) == 1 ? true : false;
                input >>= 1;
            }
        }
        int BoolArrayToInt(bool[] bits)
        {
            if (bits.Length > 32) throw new ArgumentException("Can only fit 32 bits in a int");
            int r = 0;
            for (int i = 0; i < bits.Length; i++)
            {
                if (bits[i]) r |= 1 << i;
            }
            return r;
        }
        public override string ToString()
        {
            return String.Format("Stored Date mm/dd/ss: {0}/{1}/{2}", Month, Day, Minute);
        }
    }

    class CompactDate
    {
        //Layout  Month(5)    Day(9)     Minute (12)
        //        11111       111111111  111111111111 
        public bool[] month = new bool[5];
        public bool[] day = new bool[9];
        public bool[] minute = new bool[12];
        public BitArray GetFullArray()
        {
            int fullLen = month.Length + day.Length + minute.Length;
            BitArray full = new BitArray(fullLen);
            int index = 0;
            for (int i = 0; i < month.Length; i++,index++)
            {
                full.Set(index,month[i]);
            }
            for (int i = 0; i < day.Length; i++, index++)
            {
                full.Set(index, day[i]);
            }
            for (int i = 0; i < minute.Length; i++, index++)
            {
                full.Set(index, minute[i]);
            }
            return full;
        }
        public void SetDate(BitArray arr)
        {
            int index = 0;
            for (int i = 0; i < month.Length; i++, index++)
            {
                month[i] = arr.Get(index);
            }
            for (int i = 0; i < day.Length; i++, index++)
            {
                day[i] = arr.Get(index);
            }
            for (int i = 0; i < minute.Length; i++, index++)
            {
                minute[i] = arr.Get(index);
            }
        }
    }
}
于 2013-07-26T16:15:39.437 回答
0

您可以使用分钟来表示开始时间,以防它不是在确切的时间开始,因此 24x60 = 1440 是您在开始时间中必须考虑的最高数字。以二进制表示的 1440 是 0000010110100000(2 个字节),因此数组的第一个元素 0-1 表示开始时间。接下来,您说 9999 分钟是可接受的运行时间上限,二进制为 0010011100001111(2 个字节),因此数组元素 2-3 表示运行时间。

于 2013-07-26T16:17:13.193 回答