继前天的,完成了计算阶乘,今天计算CRC32。
本来将数字转换成字符串直接使用sprintf就可以了,我在PC上也这样用,没问题。但我对DSP完全不熟悉,在DSP端的代码中使用如sprintf这些函数,结果没有得到预期效果,DSP应该不能使用这些函数吧?(注:可以使用,没得到预期效果是因为对内存操作错误造成的。)
没办法,只好自己写一个,参考网上的十进制转换字符串的做法,代码如下:
void hex_to_string(unsigned int num, char *str) { int i = 0; int n = 0; char tmp; if (num == 0) { str[0] = '0'; str[1] = '\0'; return; } while (num > 0) { tmp = num % 16; if (tmp >= 0 && tmp <= 9) str[n] = tmp + '0'; else if (tmp >= 10 && tmp <= 15) str[n] = tmp + 'A' - 0x0a; num /= 16; n++; } for (i = 0; i < n / 2; i++) { tmp = str[i]; str[i] = str[n - i - 1]; str[n - i - 1] = tmp; } str[n] = '\0'; }
函数的目的是将计算好的CRC32值转换成字符串形式,发送到ARM端。
有几个说明:
1、十进制、十六进制在内存中表现完全一样,只是printf使用不同的输出格式就得到不同的进制。传入的参数是无符号类型,如果是有符号的,结果是不正确的,像“hello world.”的CRC32值是930BDFFC,用printf的%d和%u打印的结果是不同的,如下:
930BDFFC -1827938308 2467028988
只能说,这个数就在内存中,你是有符号,还是无符号,数还是那个数,数就在那里。
2、将十进制转换成十六进制就是将十进制数除以16,取余数。这里是放到数组中,当然是ASCII码了。所以要做一个判断,当余数为0~9范围内时,说明是数字0~9,对应的ASCII码就是将这个数加上48,48、0x30、'0'都是一样的,为了阅读的方便,代码中写成'0'。当余数为10~15时,就是十六进制的'A'~'F',至于为什么要减去10,因为前面10个数是数字,不是字母。
3、上面得到的结果是反的,所以要倒过来放。为什么是反的,试一下就知道了。
4、还是前天说的,没有手动搞个'\0'上去,就不算正常的字符串,打印出来的结果会连着后面的数据。在PC上没有这种情况发生,但在DSP上,它就是发生了。不知道这个疑问到什么时候才能解决。
5、如果要提高所谓的效率,可以将tmp = num % 16;改为tmp = num & 0xf;的形式,将num /= 16;改为num >>= 4;的形式。
测试结果:
# ./loopgpp_new loop_new.out "http://www.latelee.org" the string you input: http://www.latelee.org string: http://www.latelee.org crc32: 7D696766 7D696766 =============== Sample Application : LOOP ========== Entered LOOP_Create () Leaving LOOP_Create () Entered LOOP_Execute () crc: 7D696766 37 44 36 39 36 37 36 36 0 77 2e 6c 61 74 65 6c 65 65 2e 6f 72 67 0 64 2e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 end. buffer size: 128 LOOP_NumIterations: 1 Leaving LOOP_Execute () Entered LOOP_Delete () Leaving LOOP_Delete () ====================================================
再来一个:
# ./loopgpp_new loop_new.out "hello world." the string you input: hello world. string: hello world. crc32: 930BDFFC 930BDFFC =============== Sample Application : LOOP ========== Entered LOOP_Create () Leaving LOOP_Create () Entered LOOP_Execute () crc: 930BDFFC 39 33 30 42 44 46 46 43 0 6c 64 2e 0 74 65 6c 65 65 2e 6f 72 67 0 64 2e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 end. buffer size: 128 LOOP_NumIterations: 1 Leaving LOOP_Execute () Entered LOOP_Delete () Leaving LOOP_Delete () ====================================================
上面将128个字节的缓冲区打印出来是为了更清楚里面到底是些什么东西。
PS:话说小弟接触硬件也有两三年了,CRC是知道的,但一直没有从代码上理解,前不久才在一个偶然的机会学习,代码主要来自zlib,u-boot中的crc校验也是修改自zlib,我的是综合网络资源、zlib、u-boot三者搞出来的。