我正在编写一个程序和AVR ATMEGA88,使用TI TM3705A芯片读取FDX RFID标签,并通过UART将其传输到另一个处理器。该芯片使用15625波特,而另一个处理器将以19200波特率接收数据。
想法是读取输入数据(38位ID号 - 例如00 11 E3 D6 7C),CRC检查它然后将其输出为友好的12位十进制数(000300144252),表示该ID的唯一ID标签
到目前为止,我在数组中有这个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
我正在寻找一种有效的方法来输出数组中的字节为十进制“000300144252”。
我已经尝试将它打包成long long类型然后使用sprintf%d但它似乎在temp = data<<例如32。我不知道sprintf是否会处理这个大小的数字。我承认我已经真的被C#和其他懒惰的语言所破坏了这种东西:)
有没有办法转换成十进制“你去” - 换句话说,从最高位数字(6)读取并输出UART上的十进制ASCII数字,然后5,4,3,2没有大中间缓冲区等?内存对这些芯片有点限制。
答案 0 :(得分:0)
转换为十进制计算成本很高 - 无论是自己动手还是将其委托给库函数(例如sprintf()
)都不会改变它。这里更复杂的是它是一个相对较大的值:38位,大于32位。
使用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;
}
此函数在dst[]
(终止NUL)中写出12-char结果。请注意,这意味着除以10,编译器将转换为包含相对复杂的函数。
如果你的编译器不支持long long
类型(或试图进行除法时的扼流圈),那么你必须自己实现这个操作,这需要一些数学知识。最终,this article可能有用 - 或者不是。
答案 1 :(得分:0)
经过大量的搜索和反复试验,我找到了解决方案。
我误解了我看到的错误,托马斯是对的。当添加到我自己的功能中时,该功能对于芯片来说太大了。
明显的选择没有去任何地方,但我会在这里列出它们以帮助其他新手来解决这个问题。
itoa() - 16位且 ultoa() - 实现了32位但是太小了。
sprintf(%d)太小而且WinAVR(AVR-GCC)中未实现 sprintf(%lld)。
此代码有效(警告):
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)
罪魁祸首是%运营商。我无法解释为什么长时间使用它会产生近8k的代码!
这是一个可行的替代方案。我修改它只使用无符号长long (64位),最多12位十进制数,以适应我正在使用的RFID阅读器格式。
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。