N字节无符号二进制 转 十进制BCD码(C调用汇编子程序)

2020-02-01 16:23发布

汇编子程序模块:NBYTE_BCD.asm
  1. ;========================================================================
  2. ; extern void NBYTEBCD(unsigned char idata *pri, unsigned char leni, unsigned char idata *pro, unsigned char leno);
  3. ;
  4. ; N字节无符号二进制  对应  十进制BCD码字节数
  5. ; (N <= 4 )  则 N+1   
  6. ; (N <= 9 )  则 N+2          
  7. ; (N <= 12) 则 N+3
  8. ; ……

  9. $NOMOD51

  10. NAME NBYTE_BCD                                                  ;模块名

  11. ?PR?_NBYTEBCD?NBYTE_BCD  SEGMENT CODE              ;在程序存储区中定义段     
  12. ?DT?_NBYTEBCD?NBYTE_BCD  SEGMENT DATA OVERLAYABLE
  13.         PUBLIC  ?_NBYTEBCD?BYTE
  14.         PUBLIC  _NBYTEBCD                                        ;用PUBLIC 声明函数为公共函数

  15.         RSEG          ?DT?_NBYTEBCD?NBYTE_BCD
  16. ?_NBYTEBCD?BYTE:
  17.             pri?040:   DS   1    ;R7
  18.            leni?041:   DS   1    ;R5
  19.             pro?042:   DS   1    ;R3
  20.            ORG 3
  21.            leno?043:   DS   1
  22.         RSEG    ?PR?_NBYTEBCD?NBYTE_BCD                ;用RSEG 表示函数可被连接器放置在任何地方

  23. ;========================================================================
  24. ;函数:N字节无符号二进制转十进制BCD码
  25. ;输入:*pri         
  26. ;输出:*pro
  27. ;资源:ACC、CY、R0、R1、R3、R4、R5、R7、leno?043
  28. ; ROM:59B(包括调用函数时的形参输入)

  29. _NBYTEBCD:
  30.         ;USING        0
  31.         MOV  A,R7
  32.         ADD  A,R5  
  33.         DEC  A     
  34.         MOV  R7,A
  35.        
  36.         MOV  A,leno?043
  37.         MOV  R4,A
  38.         ADD  A,R3
  39.         DEC  A      
  40.         MOV  R3,A

  41.         MOV  R0,A
  42. NP__0:
  43.          MOV  @R0,#0
  44.         DEC  R0
  45.         DJNZ R4,NP__0
  46.        
  47.         MOV  A,R5       ;转换(R5)字节二进制整数
  48.         RL   A
  49.         RL   A
  50.         RL   A
  51.         MOV  R1,A       ;计数器
  52.      CLR  C
  53. NP__1:       
  54.         MOV  A,R5
  55.         MOV  R4,A       ;循环(R5)次
  56.         MOV  A,R7
  57.         MOV  R0,A
  58. NP__2:
  59.          MOV  A,@R0      ;从高端移出待转换数的1位到CY中
  60.          RLC  A
  61.          MOV  @R0,A
  62.         DEC  R0
  63.         DJNZ R4,NP__2
  64.        
  65.         MOV  A,leno?043
  66.         MOV  R4,A       ;循环(leno)次
  67.         MOV  A,R3
  68.         MOV  R0,A
  69. NP__3:
  70.          MOV  A,@R0      ;BCD码带进位自身相加,相当于乘2
  71.          ADDC A,@R0
  72.          DA   A          ;十进制调整
  73.          MOV  @R0,A
  74.         DEC  R0
  75.         DJNZ R4,NP__3
  76.        
  77.          DJNZ R1,NP__1
  78.        
  79.          RET

  80.         END
复制代码使用方法,将 NBYTE_BCD.asm 添加到工程中,在 main.c 中声明后就可以调用,举例:
  1. unsigned char asc[8] = {0x0A,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
  2. unsigned char nz[10];

  3. extern void NBYTEBCD(unsigned char idata *pri, unsigned char leni, unsigned char idata *pro, unsigned char leno);

  4. void main(void)
  5. {
  6.         NBYTEBCD(asc, 8, nz, 10);
  7.        
  8.         while (1)
  9.         {
  10.                
  11.         }
  12. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
17条回答
BXAK
2020-02-03 02:21
本帖最后由 BXAK 于 2012-9-29 15:28 编辑
downtoearth 发表于 2012-9-29 14:28
BCD码不是用4位的二进制数表示1位的十进制数中的0-9吗?那么一个8位二进制数就是只可以表示0-99咯!
那为什 ...


1字节(即8位)无符号二进制数:0000 0000 ~ 1111 1111         
对应 十六进制:0x00 ~ 0xFF   
对应    十进制:0 ~ 255

比如想把十六进制数以十进制显示到数码管、液晶屏……时,
如果小于等于4字节时直接用除法和求余提取就可以,如:
unsigned int n = 12345;
十万位 = n/10000;
万位 = n/1000%10;
……
但如果8字节、……的十六进制数时,上面的方法行不通(keil C51支持最大的整形数据是unsigned long,4字节),这就需要把 8字节、……的十六进制数 先转成BCD


之所以弄这个程序是因为想做等精度频率计,需要公式 fx = (fo * nx) / no,其中:
unsigned long code fo = 22118400UL;
unsigned long no,nx;
运算中为了精确没有用浮点float运算,keil C51不支持double。
(fo * nx) 的积是 8字节十六进制,
(fo * nx) / no 的商是 8字节十六进制,余数是 4字节十六进制

一周热门 更多>