2

TI TM3705A チップを使用して FDX RFID タグを読み取り、それを UART 経由で別のプロセッサに送信するためのルーチンと AVR ATMEGA88 を作成しています。このチップは 15625 ボーを使用し、他のプロセッサは 19200 ボーでデータを受信します。

受信データ (38 ビットの ID 番号 - 例: 00 11 E3 D6 7C) を読み取り、CRC チェックを行ってから、タグの一意の ID を表すわかりやすい 12 桁の 10 進数 (000300144252) として出力します。

これまでのところ、配列にこの 38 ビットの数値があります。

私が興味を持っている実際の数は、要素 2:6 にあります。いいえの2つのMSBの。6 は、次のデータ ブロックの開始であるため、無視する必要があります。

i   Dec Hex Bin
0   80  50  01010000
1   126 7E  01111110
2   124 7C  01111100
3   214 D6  11010110
4   227 E3  11100011
5   17  11  00010001
6   192 C0  11000000
7   237 ED  11101101
8   0   00  00000000
9   128 80  10000000
10  97  61  01100001
11  103 67  01100111
12  126 7E  01111110
13  0   00  00000000
14  0   00  00000000

配列内のバイトを10進数の「000300144252」として出力する効率的な方法を探しています。

long long 型にパックしてから sprintf %d を使用しようとしましたが、たとえば temp = data << 32 で詰まるようです。sprintf がそのサイズの数値をまだ処理できるかどうかはわかりません。私は、この種のもののためにC#や他の怠惰な言語に本当に甘やかされてしまったことを認めます:)

「そのまま」10進数に変換する方法はありますか?つまり、最上位桁(6)から読み取り、UARTで10進数のASCII桁を出力し、大きな中間バッファなしで5,4,3,2を出力します。のような?これらのチップでは、メモリが少し制限されています。

4

2 に答える 2

0

多くの検索と試行錯誤の後、解決策を見つけました。

表示されていたエラーを誤解しましたが、トーマスは正しいです。自分の機能に追加すると、機能がチップに対して大きすぎました。

明らかな選択肢はどこにも行きませんでしたが、他の初心者がこの問題に遭遇したときに役立つように、ここにそれらをリストします.

itoa() - 16 ビットとultoa() - 32 ビットが実装されていますが、小さすぎます。

sprintf(%d)が小さすぎるため、sprintf(%lld)は WinAVR (AVR-GCC) に実装されていません。

このコードは機能します (注意事項があります):

void main()
{
    unsigned long long tagid;
    char tagid_str[12];

    tagid = 109876543210ull

    convert_to_decimal(tagid_str, tagid);
}

void convert_to_decimal(char* dst, unsigned long long src) 
{     
    int i;
    for (i = 0; i < 12; i ++) 
    {         
        dst[11 - i] = '0' + (int)(src % 10);
        src /= 10;     
    }     

    dst[12] = 0; 
} 

しかし、統計を見てください:

プログラム: 7358 バイト ( 89.8% フル) (.text + .data + .bootloader)

データ: 256 バイト ( 25.0% フル) (.data + .bss + .noinit)

原因は%演算子です。long long でそれを使用すると、ほぼ 8k のコードが生成される理由を説明できません!

これが実用的な代替手段です。使用している RFID リーダーの形式に合わせて、最大 12 桁のunsigned long long (64 ビット)のみを使用するように変更しました。

void main()
{
    unsigned long long tagid;
    char tagid_str[12];

    tagid = 000000000000ull;
    ulltostr((unsigned long long)tagid, tagid_str);

    tagid = 000000000001ull;
    ulltostr((unsigned long long)tagid, tagid_str);

    tagid = 109876543210ull;
    ulltostr((unsigned long long)tagid, tagid_str);

    tagid = 900000000000ull;
    ulltostr((unsigned long long)tagid, tagid_str);

    tagid = 999999999999ull;
    ulltostr((unsigned long long)tagid, tagid_str);
}

//http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=31199

void ulltostr(unsigned long long val, char *s ) 
{ 
  char *p; 
  unsigned char d, i; 
  unsigned char zero; 
  unsigned long long test; 
  unsigned long long uval = val; 

  p = s; 

  zero = 1; 

  i = 12; 
  do{ 
    i--;    
    if ( i==0)   test =10; 
    else if ( i==1) test =100; 
    else if ( i==2) test =1000; 
    else if ( i==3) test =10000; 
    else if ( i==4) test =100000; 
    else if ( i==5) test =1000000; 
    else if ( i==6) test =10000000; 
    else if ( i==7) test =100000000; 
    else if ( i==8) test =1000000000; 
    else if ( i==9) test =10000000000; 
    else if ( i==10) test=100000000000; 
    else if ( i==11) test=1000000000000; 
    else if ( i==12) test=10000000000000; 

    for( d = '0'; uval >= test; uval -= test ) 
    { 
      d++; 
      zero = 0; 
    } 
    if( zero == 0 ) 
      *p++ = d ; 
  }while( i ); 

  *p++ = (unsigned char)uval + '0'; 
}

そして統計:

プログラム: 758 バイト ( 9.3%フル) (.text + .data + .bootloader)

データ: 0 バイト ( 0.0%フル) (.data + .bss + .noinit)

はるかに良い:)

私はほとんどの時間をDouglas Jonesと一緒に過ごしましたが、最終的にAVR Freaksから答えが得られました。

于 2011-01-19T20:47:38.597 に答える
0

10 進数への変換は、計算コストが高くなります。自分で行うか、sprintf()変更しないなどのライブラリ関数に委譲するかに関係なく。ここでさらに複雑になっているのは、値が比較的大きいことです。つまり、32 ビットよりも大きい 38 ビットです。

sprintf()使用"%lld"して、 を印刷しlong longます。コンパイラがlong long型をサポートしていてもサポートしてsprintf()いない場合は、手動で行うことができます。

static void
convert_to_decimal(char[] dst, unsigned long long src)
{
    int i;

    for (i = 0; i < 12; i ++) {
        dst[11 - i] = '0' + (int)(src % 10);
        src /= 10;
    }
    dst[12] = 0;
}

この関数は、12 文字の結果をdst[](終端の NUL で) 書き出します。これは 10 による除算を意味することに注意してください。これは、コンパイラが比較的複雑な関数を含めることに変換します。

コンパイラがその型をサポートしていない場合long long(または除算を試みてチョークする場合)、その操作を自分で実装する必要があります。これには、少し数学的な知識が必要です。最終的に、この記事が役立つかどうかはわかりません。

于 2011-01-17T19:00:28.180 に答える