1

エンジン時間を保存したい eeprom で利用できる 56 バイトのレジスタがあります。現在、3 バイトを使用して 60 秒のタイマーをインクリメントし、情報をダウンロードしています (送信前に 9999 分を超えることはめったにありません)。

問題は、これに日付を関連付ける必要があることです。車両が始動するたびに、時間の記録を開始する必要がありますが、その時間がどの時間に増分されたかを判断する必要があります。

byte[56] 配列がある場合、日付 (または日付の 1 時間のみ) を格納し、その後に数字を格納し、それらを区別できる最も簡単な方法は何でしょうか?

送信するには、配列を反復処理して、日付または時間、および時間数を抽出する方法が必要です。

これについてのアイデアは素晴らしいでしょう、ありがとう。

レポートの最終結果は次のようになります。

06:00 - 38 分 09:00 - 60 分 10:00 - 60 分など

4

2 に答える 2

1

必要なすべてのデータを 56 バイトに収めるためのスキームのアイデアを次に示します (実際、最大 11 の日付と時刻を 56 バイトに収めることができます)。

このシステムが 1000 年以上続くとは思わないと仮定すると、年の最初の部分を定義できます。つまり、2013 年はエポックと年という 2 つに分割されます。

  • エポック: 0 ~ 31 を許可する 5 ビット (または 1 バイト)
  • 年: 0 ~ 99 を許可する 7 ビット (または 1 バイト)
  • 日: 0 ~ 365 を許可する 9 ビット (2 バイト)
  • 時間: 5 ビット (1 バイト) で 0 ~ 24 を許可
  • 2 番目: 0 ~ 3600 を許可する 12 ビット (2 バイト)

これで、単純に 7 バイトを使用してそれぞれの値をインクリメントし、最大 8 つの日付と時刻を格納できますが、構造体を作成して個々のビットをビットバンしてさらに圧縮し、40 ビットに詰め込むことができます (または 5 バイト) 11 の日付を許可します。

本当に詰め込みたい場合はエポックを削除することもできますが、上記のスキームでは 3199 までの日付を操作できます。

他のよりコンパクトな方法があると確信しています。つまり、1970 年 1 月 1 日からのミリ秒数は、数年後に数ビット減少する可能性がありますが、コードの寿命は短くなりますが、私は見ていません実際の値。

いくつかのサンプル コード (bool は内部的にはバイト (?!) であるため、BitArray を使用するように更新されていますが、BitArray は実際にはビットです... OPS の場合は非常に重要です。:

OPは、1時間ごとに運転された分の量を保存したいと考えていることに注意する必要がありますが、これにはさらに多くのスペースが必要になります(運転した1時間ごとの記録または日付を示す毎日の開始および停止記録) (結局、停止は開始の後に来る必要があります。) 以下のコードを使用すると、特定の日に何分運転されたかを記録できます。

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 に答える