搜索
bottom↓
回复: 16

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

[复制链接]

出0入0汤圆

发表于 2012-9-28 21:58:35 | 显示全部楼层 |阅读模式
汇编子程序模块: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. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2012-9-29 06:43:35 | 显示全部楼层
汇编没有看懂,为什么不用C写一个呢,速度问题吗?

出0入0汤圆

 楼主| 发表于 2012-9-29 09:15:20 | 显示全部楼层
downtoearth 发表于 2012-9-29 06:43
汇编没有看懂,为什么不用C写一个呢,速度问题吗?

用C写这个N字节转换还真不会,
如果你有C写的可否帖上来

出0入0汤圆

发表于 2012-9-29 09:55:09 | 显示全部楼层
/*
* @brief  exchange the data to BCD
* @param  *source : the data to exchange
* @param  *target : the data exchanged
* @param  number :        the bytes of source to change
* @retval None
*/
void Tool_ChangeTo_BCD(rt_uint8_t *source,rt_uint8_t *target,rt_uint8_t number)
{
        rt_uint8_t count;
        rt_uint8_t length;

        length = number;
        for(count = 0;count < length;count++)
        {
                if(count%2 == 0)
                {
                        *(target + count/2) = *(source + count);
                        *(target + count/2) &= 0x0F;
                }
                if(count%2 == 1)
                {
                        *(target + count/2) |= (*(source + count)<<4);
                }
        }
}

出0入0汤圆

 楼主| 发表于 2012-9-29 10:47:32 | 显示全部楼层
Rookie_li 发表于 2012-9-29 09:55
/*
* @brief  exchange the data to BCD
* @param  *source : the data to exchange


这个程序好像是N位十进制 转 BCD码,而不是 N字节无符号二进制 转 BCD码

出0入0汤圆

发表于 2012-9-29 12:39:52 | 显示全部楼层
我真心不会,只是我只会C,所以才问问.

出0入0汤圆

发表于 2012-9-29 14:05:24 | 显示全部楼层
想了一会写了这程序,我还是很菜,有什么错误的地方望大家多点指导,口下流情。
  1. #include <STRING.H>
  2. uchar Data[]= {0x0A,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
  3. uchar BCD[]={0};
  4. uchar Four_Bit_BCD (uchar Data)
  5. {
  6. uchar Data_Temp ;
  7. switch (Data)
  8.         {
  9.                  case 0 : Data_Temp = 0x00 ; break ;
  10.                  case 1 : Data_Temp = 0x01 ; break ;
  11.                  case 2 : Data_Temp = 0x02 ; break ;
  12.                  case 3 : Data_Temp = 0x03 ; break ;
  13.                  case 4 : Data_Temp = 0x04 ; break ;
  14.                  case 5 : Data_Temp = 0x05 ; break ;
  15.                  case 6 : Data_Temp = 0x06 ; break ;
  16.                  case 7 : Data_Temp = 0x07 ; break ;
  17.                  case 8 : Data_Temp = 0x08 ; break ;
  18.                  case 9 : Data_Temp = 0x09 ; break ;
  19.                  default : break ;
  20.                 }
  21. return Data_Temp ;
  22. }

  23. void Data_Change_BCD(uchar *Data_P,uchar *BCD_P)
  24. {
  25. uchar i ;
  26. uchar Data_Temp_L,Data_Temp_H;
  27. i=strlen(Data_P);
  28. for (; i>0; i--)
  29.       {
  30.            Data_Temp_L = *Data_P  % 10 ;
  31.            Data_Temp_H = *Data_P  / 10 ;
  32.            *BCD_P = Four_Bit_BCD( Data_Temp_H )<<4+Four_Bit_BCD( Data_Temp_L );
  33.            Data_P++;
  34.            BCD_P++ ;
  35.           }
  36. }
复制代码

出0入0汤圆

 楼主| 发表于 2012-9-29 14:19:43 | 显示全部楼层
downtoearth 发表于 2012-9-29 14:05
想了一会写了这程序,我还是很菜,有什么错误的地方望大家多点指导,口下流情。 ...

好像不对头,比如:
十六进制0xFF = 十进制255,将 十六进制0xFF 转换成 BCD 结果应该是 0x0225
十六进制0x0FFF FFFF FFFF FFFF = 十进制1,152,921,504,606,846,975,将 十六进制0x0FFF FFFF FFFF FFFF 转换成 BCD 结果应该是 0x01152921504606846975

出0入0汤圆

发表于 2012-9-29 14:28:09 | 显示全部楼层
本帖最后由 downtoearth 于 2012-9-29 14:31 编辑

BCD码不是用4位的二进制数表示1位的十进制数中的0-9吗?那么一个8位二进制数就是只可以表示0-99咯!
那为什么有0xAA的数据的。不明白,跟帖弄个究竟.理解错,我再想想!

出0入0汤圆

 楼主| 发表于 2012-9-29 15:20:08 | 显示全部楼层
本帖最后由 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字节十六进制

出0入0汤圆

发表于 2012-9-29 15:34:15 | 显示全部楼层
本帖最后由 downtoearth 于 2012-9-29 15:36 编辑

改成这样不知可以不可以,我都不知用什么来测试这段代码。
  1. #include <STRING.H>
  2. #include "MacroAndConst.H"
  3. uchar Data[]= {0x0F,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF};
  4. uchar BCD[]={0};
  5. uchar Four_Bit_BCD (uint Data)
  6. {
  7. uchar Data_Temp ;
  8. switch (Data)
  9.         {
  10.                  case 0 : Data_Temp = 0x00 ; break ;
  11.                  case 1 : Data_Temp = 0x01 ; break ;
  12.                  case 2 : Data_Temp = 0x02 ; break ;
  13.                  case 3 : Data_Temp = 0x03 ; break ;
  14.                  case 4 : Data_Temp = 0x04 ; break ;
  15.                  case 5 : Data_Temp = 0x05 ; break ;
  16.                  case 6 : Data_Temp = 0x06 ; break ;
  17.                  case 7 : Data_Temp = 0x07 ; break ;
  18.                  case 8 : Data_Temp = 0x08 ; break ;
  19.                  case 9 : Data_Temp = 0x09 ; break ;
  20.                  default : break ;
  21.                 }
  22. return Data_Temp ;
  23. }

  24. void Data_Change_BCD(uchar *Data_P,uchar *BCD_P)
  25. {
  26. uchar i ;
  27. uint Data_Temp_1,Data_Temp_2,Data_Temp_3 ;
  28. i=strlen(Data_P);
  29. for (; i>0; i--)
  30.       {
  31.         *Data_P += Data_Temp_3 ;
  32.          Data_Temp_1 = *Data_P  % 10 ;
  33.          Data_Temp_2 = *Data_P  / 10 ;
  34.            if ( Data_Temp_2 > 9 )               {
  35.                                                                 Data_Temp_3 = Data_Temp_2 - 9 ;   
  36.                                                                 Data_Temp_2 = 9 ;  
  37.                                                            }
  38.                else Data_Temp_3 = 0 ;
  39.           
  40.            *BCD_P = Four_Bit_BCD( Data_Temp_2 )<<4+Four_Bit_BCD( Data_Temp_1 );
  41.            Data_P++;
  42.            BCD_P++ ;
  43.           }
  44. if ( Data_Temp_3 != 0 )
  45.       {
  46.            BCD_P += 1;
  47.            Data_Temp_1 = Data_Temp_3 % 10 ;
  48.            Data_Temp_2 = Data_Temp_3 / 10 ;
  49.            *BCD_P = Four_Bit_BCD( Data_Temp_2 )<<4+Four_Bit_BCD( Data_Temp_1 );
  50.           }
  51. }
复制代码

出0入0汤圆

发表于 2012-9-29 15:43:55 | 显示全部楼层
本帖最后由 downtoearth 于 2012-9-29 16:04 编辑
BXAK 发表于 2012-9-29 15:20
1字节(即8位)无符号二进制数:0000 0000 ~ 1111 1111         
对应 十六进制:0x00 ~ 0xFF   
对应   ...


哦,原来是这样,好复杂呀,不过我在keil51中用过double型数据修饰符,为什么编译器没有报错的。运算正确奇怪!

出0入0汤圆

 楼主| 发表于 2012-9-29 16:31:18 | 显示全部楼层
downtoearth 发表于 2012-9-29 15:43
哦,原来是这样,好复杂呀,不过我在keil51中用过double型数据修饰符,为什么编译器没有报错的。运算正确 ...

keil51中用double 编译器会自动转成 float,精度只有6位小数,1.23456789 变成 1.234568
调试窗口如下:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-9-29 19:06:18 | 显示全部楼层
BXAK 发表于 2012-9-29 16:31
keil51中用double 编译器会自动转成 float,精度只有6位小数,1.23456789 变成 1.234568
调试窗口如下:
...


哦,原来是这样,我想再问问你这个是什么软件,不是keil呀,是周立功那个程序编辑软件吗?

出0入0汤圆

 楼主| 发表于 2012-9-29 20:37:49 | 显示全部楼层
downtoearth 发表于 2012-9-29 19:06
哦,原来是这样,我想再问问你这个是什么软件,不是keil呀,是周立功那个程序编辑软件吗? ...

keil C51 最新版 9.50a

出0入0汤圆

发表于 2013-1-6 15:44:36 | 显示全部楼层
很喜欢楼主的态度。。敬佩
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-22 06:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表