首页 > 解决方案 > 我正在使用 PSoC 5。我想知道从 EEPROM 读取后如何将 8 字节十六进制转换为十进制

问题描述

EEPROM数据:

0000: 88 77 66 55 44 33 22 11 00 00 00 00 00 00 00 00

0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

我在读取数组中的第 0 行 EEPROM 后保存结果

Ex - Uint8 EEPROM_res[8];

 EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};

我想将 HexaDecimal(0x8877665544332211) 转换为十进制 (9833440827789222417) 并将十进制值保存为整数数据类型以供进一步比较。8字节十六进制的最简单转换方法是什么?

标签: cembeddedmicrocontrollerpsoccypress-psoc

解决方案


可以分享一下算法吗?– Shivangi Kishore

将基数 10(秒)转换为基数 60(时:分:秒)

4321 秒(以 10 为底)到以 60 为底。

60^0 = 1
60^1 = 60
60^2 = 3600
60^3 = 216000

(就像 10^0 = 1、10^1 = 10 和 10^2 = 100 ... base 10、2^0 = 1、2^1 = 2、2^2 = 4 等等以 2 为底)

所以 4321 小于 216000 但大于 3600 所以我们可以快捷地从那里开始

4321 / 3600 = 1 remainder 721
721 / 60 = 12 remainder 1

所以 4321 base 10 转换为 base 60(使用 base 10 来做数学)是 01:12:01

使用base 2 计算机的base 2 到base 10 没有什么不同。

2 和 5 有 10 个因数,2 有 2 个因数,所以你不能做以 8(八进制)为底的 2 快捷方式,也不能以 16(十六进制)来做以 2 为底的快捷方式。必须走很长的路。

编辑

另一种可能对您更有用的方法是从另一端工作。刚刚使用余数而不是结果完成了相同的数学运算。使算法更容易编程。

4321 / 60 = 72 余数 1 72 / 60 = 1 余数 12 1 / 60 = 0 余数 1 转换为基数 60:01:12:01

1234 / 10 = 123 余数 4 123 / 10 = 12 余数 3 12 / 10 = 1 余数 2 1 / 10 = 0 余数 1 转换为基数 10:1234

二进制中的长除法与大于 2 的基数相同但更简单,因为通过分母的每一步的除数可以进入测试值 0 次或 1 次。二进制...基数 2...

此外,如果您考虑长除法(254 / 5 或 0xFE / 0x5)

    ------------
101 ) 11111110

这是第一个非零的测试用例

      001
    ------------
101 ) 11111110
      101

你继续前进

      001
    ------------
101 ) 11111110
      101
      ---
       10

      0011
    ------------
101 ) 11111110
      101
      ---
       101
       101
       ---
         0

      00110010
    ------------
101 ) 11111110
      101
      ---
       101
       101
       ---
         0111
          101
          ---
           100

所以 0xFE / 5 = 0x32 余数 4,但这里的关键是,如果我说 8 位除法指令并且想要除以无限长的数字,我可以使用硬件除法指令在硬件中做到这一点。如果我的下一个(比方说)四位数是 1010:

     0001110
101  1001010
      101
      ===
      1000
       101
       ===
        111
        101 
        ===
         100

0xFEA / 5 = 0x32E 余数 4

所以现在我已经使用 8 位除法器指令划分了一个 12 位数字,我可以整天这样做,直到我用完 ram。8 位、88 位、888 位、8888 位、一百万位除以 5 或 10 之类的小数。

或者,如果您继续研究这个问题,您会发现编译器经常使用乘法,我们从小学也知道(因为所有这些问题都通过小学数学解决)。

x / 10 = x * (1/10)

更有可能找到硬件乘法而不是除法,并且乘法通常需要更少的时钟,等等。

unsigned int fun ( unsigned int x )
{
    return(x/10);
}
00000000 <fun>:
   0:   e59f3008    ldr r3, [pc, #8]    ; 10 <fun+0x10>
   4:   e0802093    umull   r2, r0, r3, r0
   8:   e1a001a0    lsr r0, r0, #3
   c:   e12fff1e    bx  lr
  10:   cccccccd    stclgt  12, cr12, [r12], {205}  ; 0xcd


0000000000000000 <fun>:
   0:   89 f8                   mov    %edi,%eax
   2:   ba cd cc cc cc          mov    $0xcccccccd,%edx
   7:   f7 e2                   mul    %edx
   9:   89 d0                   mov    %edx,%eax
   b:   c1 e8 03                shr    $0x3,%eax
   e:   c3                      retq   

和其他指令集,编译器乘以 1/5 然后进行补偿(以 10 为底,2 和 5 乘以 10,以 2 为底,2 乘以 2 公因数)。

但是如果您的硬件没有乘法或除法,编译器仍应处理基本的 C 语言变量类型,long、int、short、char。你可以整天级联这些。

unsigned int fun ( unsigned int x )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;

    ra=((x>>4)&0xFF)/5;
    rb=((x>>4)&0xFF)%5;
    rb=(rb<<4)|(x&0xF);
    rc=rb/5;
    ra=(ra<<4)|rc;
    return(ra);
}

在开发机上测试

#include <stdio.h>
extern unsigned int fun ( unsigned int );
int main ( void )
{
    printf("%X\n",fun(0xFEA));
    return(0);
}

输出为 0x32E。

这真的完成了你需要知道的一切(你从小学就已经知道了)用你可用的工具进行转换。

相反,如果您正在为某个目标的某个编译器寻找一些大型数学库,那么让我们为您搜索东西不是 Stack Overflow 问题,并且应该在寻找外部或第三方库时关闭。

现在正如指出的那样

将十进制值保存为整数数据类型以供进一步比较

没有任何意义,如果您想取一些数字然后将其保存以在计算机上进行进一步比较,则该功能如下所示

void fun ( void )
{
}

它已经是那种形式,你希望它是一个整数,表示某个变量(大于 C 支持的,所以这是问题措辞的另一个问题),所以这意味着二进制而不是十进制,所以它已经在未来具有可比性整数形式。

如果您想以某种基数直观地表示该数字(如在人类可见的打印输出中),那么您需要将其转换为可以查看的东西,无论是基数 2(二进制)、基数 8(八进制)、基数 16(十六进制) , 以 10 为底(十进制)等等。

计算机中的 11111111 位,如果我想看到二进制的,然后是八进制的“11111111”,十六进制的“377”,十进制的“FF”,十进制的“255”,所有这些都需要一个算法来转换。八进制和十六进制当然是最简单的,不需要使用除法例程转换为八进制,以 8 为底,因数为 2 2 2 基数为 2,因此 2^3 vs 2^1

11111111 / 8 = 11111111 >> 3 = 11111 r 111
11111 / 8 = 11111 >> 3 = 11 r 111
11 / 8 = 11 >> 3 = 0 r 11
377

以 10 为基数,尽管您必须走很长的路并实际进行除法并找到余数,直到循环中除法的结果为 0。10 具有因数 2 和 5,2 具有因数 2,您无法通过它。以 100、10*10 和 10 为基数,您可以通过(就像从 2 基数到 4 基数一样)但是从 2 基数到 10 基数,不能。

11111111 / 10 = 11001 r 101
11001 / 10 = 10 r 101
10 / 10 = 0 r 10
255

这当然就是为什么我们非常喜欢以十六进制而不是十进制查看计算机上的内容的原因。

一次是十进制

"for further comparison"

一旦你得到它以 10 为底,那么你可以与其他以 10 为底的数字进行的唯一合理比较是字符串比较或数组比较,从上面的例子中,你可以存储该转换的两种更常见的方式是 0x32、0x35、0x35, 0x00 或 0x02, 0x05, 0x05 有一些长度知识。如果没有大量的工作,你不能做得更多。相等与不相等,您可以以 10 位为底,它不是整数形式。

所以你的问题没有任何意义。

还假设这是一个多部分错字:

EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};

这与

EEPROM_res = {0x58,0x4D,0x42,0x37,0x2C,0x21,0x16,0x0B};

两者都不是

EEPROM_res = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};

正如您所提到的,这就是您的前 8 个字节的 eeprom 转储以十六进制显示的内容,并且有些明显。

他们也不是

EEPROM_res[19] = {0x39,0x38,0x33,0x33....and so on
or
EEPROM_res[19] = {0x09,0x08,0x03,0x03....and so on

您以某种方式计算的十进制值:9833440827789222417


推荐阅读