文档库 最新最全的文档下载
当前位置:文档库 › 二进制与BCD码转换资料

二进制与BCD码转换资料

16位二进制数转换成BCD码的的快速算法-51单片机2010-02-18 00:43在做而论道上篇博文中,回答了一个16位二进制数转换成BCD码的问题,给出了一个网上广泛流传的经典转换程序。

程序可见:https://www.wendangku.net/doc/2f5186259.html,/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/6154551f93ba561440341732.html中的HEX2BCD子程序。

.

说它经典,不仅是因为它已经流传已久,重要的是它的编程思路十分清晰,十分易于延伸推广。做而论道曾经利用它的思路,很容易的编写出了48位二进制数变换成16位BCD码的程序。

但是这个程序有个明显的缺点,就是执行时间太长,转换16位二进制数,就必须循环16遍,转换48位二进制数,就必须循环48遍。

上述的HEX2BCD子程序,虽然长度仅仅为26字节,执行时间却要用331个机器周期。

.

单片机系统多半是用于各种类型的控制场合,很多时候都是需要“争分夺秒”的,在低功耗系统设计中,也必须考虑因为运算时间长而增加系统耗电量的问题。

为了提高整机运行的速度,在多年前,做而论道就另外编写了一个转换程序,程序的长度为81字节,执行时间是81个机器周期,(这两个数字怎么这么巧!) 执行时间仅仅是经典程序的1/4!

.

近来,在网上发现了一个链接:https://www.wendangku.net/doc/2f5186259.html,/news/Article/uc/uc8051/200803/4751.html,也对这个经典转换程序进行了改进,话是说了不少,只是没有实质性的东西。这篇文章提到的程序,一直也没有找到,也难辩真假。

这篇文章好像是选自某个著名杂志,但是在术语的使用上,有着明显的漏洞,不像是专业人员的手笔。比如说文中提到的:“使用51条指令代码,但执行这段程序却要耗费312个指令周期”,就是败笔。51条指令代码,真不知道说的是什么,指令周期是因各种机型和指令而异的,也不能表示确切的时间。

.

下面说说做而论道的编程思路。

;-----------------------------------------------------------------------

;已知16位二进制整数n以b15~b0表示,取值范围为0~65535。

;那么可以写成:

; n = [b15 ~ b0]

;把16位数分解成高8位、低8位来写,也是常见的形式:

; n = [b15~b8] * 256 + [b7~b0]

;那么,写成下列形式,也就可以理解了:

; n = [b15~b12] * 4096 + [b11~b0]

;式中高4位[b15~b12]取值范围为0~15,代表了4096的个数;

;上式可以变形为:

; n = [b15~b12] * 4000 + {[b15~b12] * (100 - 4) + [b11~b0]}

;用x代表[b15~b12],有:

; n = x * 4000 + {x * (100 - 4) + [b11~b0]}

;即:

; n = 4*x (千位) + x (百位) + [b11~b0] - 4*x

;写到这里,就可以看出一点BCD码变换的意思来了。

;

;上式中后面的位:[b11~b0] - 4*x,如果小于256,那就太简单了,马上就可以去按照常

规转换BCD了。

;如果数值较大,就要把[b11~b7]看成128的个数y;在百位中加上y、在十位加上3*y、并在[b6~b0]中减去2*y。

;那么就有:

; n = 4*x (千位) + x (百位) + [b11~b0] - 4*x

; n = 4*x (千位) + (x + y) (百位) + 3*y (十位) + [b6~b0] - 2*y

;由此,就可以明确由高9位[b15~b7]变换出来十进制的各个位的数值,可能大于9,到最后整理一下即可。

;剩下的低7位[b6~b0],已经是单字节数据,变换成BCD码那就十分简单了。

;-----------------------------------------------------------------------

从最后的表达式中可以看出,高9位变换的计算方法极为简单,只是使用左移、加减等指令即可,基本上不涉及多字节的运算。

编程的时候,要充分利用单字节、单周期的指令,使程序的长度和执行时间尽量缩短。

做而论道的编程思路已经给出,程序代码还是过一段时间再公布,给大家留下一个发挥的时间。

感兴趣的网友可以留言,写出自己编写的程序。



51单片机把4位16进制数转成10进制数的方法2010-02-10 23:33, 2位16进制转10进制,用除以10求商跟余数的方法,即可。
4位16进制数呢?DIV指令只可以对2位16进制数进行除法运算啊,求高手解答。
例如把TH1 TL1的数值转成十进制, 分别存入R4 R3 R2 R1 R0。
我要的是汇编的方法,C语言还没学到。
悬赏分:30 - 解决时间:2010-2-10 22:47
;------------------------------------------------------------------
最佳答案:两个字节的二进制数转换成BCD码,必须编写程序来解决。
下面把这段转换程序,写成子程序的结构,便于网友移植。
;
程序经过仿真调试通过,如下所示:
;------------------------------------------------------------------
;
MOV R0, TH1
MOV R1, TL1
CALL HEX2BCD ;调用子程序把R0 R1中的数字,转换成压缩的BCD码,送到R2 R3 R4

;-------下面,把万千百十个位,分别存入R4 R3 R2 R1 R0

MOV A, R4 ;先分离R4中的压缩型BCD码,包含的是十位与个位的数
MOV B, #16
DIV AB ;除以16,目的是分离出高、低四位
MOV R1, A ;存放十位
MOV R0, B ;存放个位
;
MOV A, R2 ;万位数不超过6,即R2中的压缩型BCD码只有一个,直接放到万位R4中
MOV R4, A ;存放万位
;
MOV A, R3 ;分离R3中的压缩型BCD码,其包含的是千位和百位数
MOV B, #16 ;半字节分离
DIV AB
MOV R3, A
MOV R2, B

SJMP $ ;到此,完成了题目要求
;------------------------------------------------------------------
;两个字节的二进制数转换成BCD码的程序如下:
;功能:16位二进制数变换成为 BCD 码;
;入口:R0 R1 中是 16 位二

进制数,其中R0中是高 8 位;
;出口:R2 R3 R4 中是 BCD 码,其中R2中是万位,R3中是千、百位,R4中是十、个位。
HEX2BCD:
CLR A
MOV R2, A ;先对要放入转换后的压缩型BCD码的寄存器通通清零
MOV R3, A
MOV R4, A
MOV R5, #16 ;共转换十六位数
LOOP:
CLR C
MOV A, R1 ;从待转换数的高端移出一位到Cy(从低8位R1开始转换)
RLC A
MOV R1, A
MOV A, R0
RLC A
MOV R0, A
MOV A, R4 ;送到BCD码的低端
ADDC A, R4 ;带进位加。自身相加,相当于左移一位
DA A ;十进制调整,变成BCD码
MOV R4, A
MOV A, R3
ADDC A, R3
DA A
MOV R3, A
MOV A, R2
ADDC A, R2
MOV R2, A
DJNZ R5, LOOP ;共转换十六位数
RET




将A中的二进制数转换为3位的BCD码,其中百位数存放......2010-01-11 09:13请各位懂得帮写下这个程序片段。

将A中的二进制数转换为3位的BCD码。其中百位数存放到31H中,十位和个位数压缩后,存放到30H中。

悬赏分:80 - 解决时间:2009-10-19 09:59

最佳答案:

;------------------------------------------

看来这个题目是属于MCS-51单片机的。

下面用51单片机的汇编语言来求解。


MOV B, #100

DIV AB

MOV 31H, A ;存百位数

MOV A, #10

XCH A, B

DIV AB

SWAP A ;十位数换到高四位

ADD A, B ;加上个位数

MOV 30H, A ;保存



R0中的8位二进制数转换成3位BCD码 -单片机编程2010-01-10 23:18单片机的不难编程题!急!!!!!!

将R0中的8位二进制数转换成3位BCD码,结果存入外部RAM的1002H~1000H(从高位到低位)单元中。

例如:地址:R0 执行后:1002H 1001H 1000H

数据:81H 01 02 09

悬赏分:15 - 解决时间:2009-10-15 19:10

提问者: stefine_ - 一级

最佳答案:

;-------------------------------------------------------

呵呵,楼上的程序,使用了DEC DPTR,要知道,51单片机指令系统里面,是没有DEC DPTR指令的。

按照下面的思路做,还可以再简练些。

R0中的8位二进制数转换成3位BCD码:

MOV DPTR, #1000H ;个位的地址

MOV A, R0

MOV B, #10

DIV AB

XCH A, B

MOVX @DPTR, A

INC DPTR

MOV A, #10

XCH A, B

DIV AB

XCH A, B

MOVX @DPTR, A

INC DPTR

XCH A, B

MOVX @DPTR, A

RET

 

仅用了24字节



16位二进制转BCD码 --单片机2010-01-03 14:19要求:编写一段程序,把计数器中T0中计的数(TH0和TL0)转成8421BCD码。

并且高8位给p

1口,低8位给p0口,要是转成BCD码超过16位,则给p2.0高电平。

我是做单片机课设的,这段程序实在编不明白了,向各位大侠请教了!无比感谢中!

答对有额外加分啊!!!!

悬赏分:200 - 解决时间:2010-1-3 13:03

最佳答案:16bit 表示:65536,万位不超6

――――――――――――――――――――――――――

程序如下:
MOV R0, TL0 ;
MOV R1, TH0 ;待转换的16bit数分别放入(由高到低)R1R0中
;
CLR A
MOV R2, A ;先清零
MOV R3, A
MOV R4, A
MOV R5, #16 ;共转换16位数
LOOP:
CLR C ;c=0
MOV A, R0 ;从待转换低8bit数的高端移出一位到Cy(转换最先由低8位开始)
RLC A ;R0中的最高位移入到A中
MOV R0, A
MOV A, R1 ;(高8位二进制数)
RLC A ;此时C中的由低8位所移入的数重新移入高8位的低端
MOV R1, A ;相当于16bit的高端移出了1bit到C中了

MOV A, R4 ;送到BCD码的低端
ADDC A, R4 ;带进位加。自身相加,相当于左移一位
DA A ;十进制调整,变成BCD码
MOV R4, A

MOV A, R3
ADDC A, R3
DA A
MOV R3, A
MOV A, R2
ADDC A, R2
MOV R2, A
DJNZ R5, LOOP ;循环16遍, 转换即完成
;
MOV P0, R4 ;按照要求输出
MOV P1, R3
CLR P2.0
MOV A, R2
JZ P20_L
SETB P2.0
P20_L:
RET



如果随意对一个累加器A中的二进制数据进行“二进制转十进制”调整是没有任何实际意义的!

DA调整的对象是在ADD或ADDC之后的结果,而且是以BCD码相加以后才能够调整,否则没有实际意义!

比如,现在要执行12D+39D也就是两个十进制数相加这样一个加法(有时候程序处理的需要,数据在单片机中是以BCD码的形式存储的,也就是12H和39H(十六进制),但我们可以人为将它们看为12D和39D(十进制),而且还希望相加以后的结果为51H,也就是说符合十进制运算规则12+39=51,而不是4BH的结果),但这样的十进制加法运算在单片机中是不能够直接实现的。因为单片机只能够执行二进制加法指令,也就是所有的运算都按照二进制中的规则进行!

于是就出现了DA调整指令!

现在12H+39H,将12H放于A中,执行 ADD A,#39H指令,则结果为4BH,这不是我们希望的51H的数据形式!!这时执行DA A 指令后,就会将A中的数据调整为51H(具体调整过程和原理你可以详细看书,如果单片机书中讲的不详细,那么微机原理中一定说的非常详细),而我们按照BCD码规则就将其看为51D,符合我们的要求!


也就是说加数和被加数都是BCD码的形式,最大也只可能是99H,也就是我们十进制数中的99,只有这样才会有实际的意义!所以你说的当A=#24H的时候的情况是不会存在的,严格的说是没有意义的!

而且DA A指令只用于十进制BCD码加法指令 ADD/ADDC 以后,否则是没有实际意义的!



定义:用4位二进制数来表示1位十进制数中的0~9这10个数码,简称BCD码
即BCD代码。Binary-Coded Decimal?,简称BCD,称BCD码或二-十进制代码,亦称二进码十进数。是一种二进制的数字编码形式,用二进制编码的十进制代码。这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。
由于十进制数共有0、1、2、……、9十个数码,因此,至少需要4位二进制码来表示1位十进制数。4位二进制码共有2^4=16种码组,在这16种代码中,可以任选10种来表示10个十进制数码,共有N=16!/(16-10)!约等于2.9乘以10的10次方种方案。常用的BCD代码列于末。
常用BCD编码方式
最常用的BCD编码,就是使用"0"至"9"这十个数值的二进码来表示。这种编码方式,在中国大陆称之为“8421码”。除此以外,对应不同需求,各人亦开发了不同的编码方法,以适应不同的需求。这些编码,大致可以分成有权码和无权码两种:
有权BCD码,如:8421(最常用)、2421、5421…
无权BCD码,如:余3码、格雷码…
以下为三种常见的BCD编码的比较。
十进数 8421-BCD码 余3-BCD码 2421-A码
(M10) D C B A C3 C2 C1 C0 a3 a2 a1 a0
0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 0 0 1 0 1 0 0 0 0 0 1
2 0 0 1 0 0 1 0 1 0 0 1 0
3 0 0 1 1 0 1 1 0 0 0 1 1
4 0 1 0 0 0 1 1 1 0 1 0 0
5 0 1 0 1 1 0 0 0 0 1 0 1
6 0 1 1 0 1 0 0 1 0 1 1 0
7 0 1 1 1 1 0 1 0 0 1 1 1
8 1 0 0 0 1 0 1 1 1 1 1 0
9 1 0 0 1 1 1 0 0 1 1 1 1
常用BCD码
十进制数 8421码 5421码 2421码 余3码 余3循环码
0 0000 0000 0000 0011 0010
1 0001 0001 0001 0100 0110
2 0010 0010 0010 0101 0111
3 0011 0011 0011 0110 0101
4 0100 0100 0100 0111 0100
5 0101 1000 1011 1000 1100
6 0110 1001 1100 1001 1101
7 0111 1010 1101 1010 1111
8 1000 1011 1110 1011 1110
9 1001 1100 1111 1100 1010
-----------------------
特点:
8421编码直观,好理解。
5421码和2421码中大于5的数字都是高位为1,5以下的高位为0。
余3码是8421码加上3,有上溢出和下溢出的空间。
格雷码相邻2

个数有三位相同,只有一位不同。
————————————————————
什么是BCD码2006-3-19 13:24:45
bcd码也叫8421码就是将十进制的数以8421的形式展开成二进制,大家知道十进制是0~9十个数组成,着十个数每个数都有自己的8421码:
0=0000
1=0001
2=0010
3=0011
4=0100
5=0101
6=0110
7=0111
8=1000
9=1001
举个例子:
321的8421码就是
3 2 1
0011 0010 0001
原因:0011=8x0+4x0+1x2+1x1=3 0010=8x0+4x0+2x1+1x0=2. 0001=8x0+4x0+2x0+1x1=1
具体:
bcd码是四位二进制码, 也就是将十进制的数字转化为二进制, 但是和普通的转化有一点不同, 每一个十进制的数字0-9都对应着一个四位的二进制码,对应关系如下: 十进制0 对应 二进制0000 ;十进制1 对应二进制0001 ....... 9 1001 接下来的10就有两个上述的码来表示 10 表示为00010000 也就是BCD码是遇见1001就产生进位,不象普通的二进制码,到1111才产生进位10000
举例:
某二进制无符号数11101010,转换为三位非压缩BCD数,按百位、十位和个位的顺序表示,应为__C__。
A.00000001 00000011 00000111 B. 00000011 00000001 00000111
C.00000010 00000011 00000100 D. 00000011 00000001 00001001
解:(1)11101010转换为十进制:234
(2)按百位、十位和个位的顺序表示,应为__C__。
附注:压缩BCD码与非压缩BCD码的区别—— 压缩BCD码的每一位用4位二进制表示,一个字节表示两位十进制数。例如10010110B表示十进制数96D;非压缩BCD码用1个字节表示一位十进制数,高四位总是0000,低4位的0000~1001表示0~9.例如00001000B表示十进制数




关于MCS-51单片机是如何将单字节二进制数转化为BCD码的问题
悬赏分:20 - 解决时间:2010-5-5 15:15
程序如下:BINBCD:MOV B, #100 (100作为除数送入B中)
DIV AB (十六进制数除以100)
MOV R3, A (百位数送r3,余数放入B中)
MOV A, #10 (分离十位数与个位数)
XCH A,B (余数放入A中,除数放入B中)
DIV AB (分离出十位在A中,个位在B中)
SWAP A (十位数交换到A的高4位)
ADD A,B (十位数与个位数相加送入 A中)
END
1 请问这个程序求解的思路是什么?2 该程序的第二句"DIV AB"的解释是十六进制数除以100,可是A中应该存放的是一个八位的二进制数,这是怎么回事?3 最后为什么要十位数与个位数相加,不是要分离十位数与个位数吗?




乘除法的时候可以不考虑进制的,比如说 #0FFH这个十六进制数 存放于A中,#100这个十进制数放于B中 然后DIV AB 这时 A等于#02H B等于#37H等于55
在然后

假设A中的数为 FFH
BINBCD:
MOV B, #100 (B=100,十进制100,)
DIV AB (A等于#02H,B等于#37H等于55)
MOV R3, A (A=02H)
MOV A, #10 (A=10=0AH,B=55=37H)
XCH A,B (A=55=37H, B=10=0AH)
DIV AB (A=05H=5 , B=5=05H)
SWAP A (A=50H,B=05H)
ADD A,B (A=55H,这时十位各位的BCD吗已经求出来了,将
37H=55转换为55H
END
1 请问这个程序求解的思路是什么?
思路就是对一个数求模和求于来分离百位十位和个位
例如168
168/100=1余68
68/10=6余8
8/1=8余0
这样就分离了百位十位和个位
2 该程序的第二句"DIV AB"的解释是十六进制数除以100,可是A中应该存放的是一个八位的二进制数,这是怎么回事?
这个是你没理解cpu存数据的方式,A中存放的其实归根结底说是二进制数,机器只认识二进制数,对这段程序编译之后我们输入的十进制100也变成二进制数了,我们通常说十六进制数是因为十六进制数和二进制数有位上的对应关系,比如1100 0110B=C6H 也就是说二进制数每4位一段各自写成十六进制数就把二进制转换成十六进制了,
3 最后为什么要十位数与个位数相加,不是要分离十位数与个位数吗?
我想如果你清楚BCD码的含义你就明白了
BCD码就是用十六进制数来表示十进制的数
例如:45H是等于十进制的69的,但如果你说他是BCD码他就代表十进制数45
这样你就会发现不是每个十六进制数都是BCD码的,例如AAH就不是BCD码,因为没有AA这样的十进制数

我最后总结一下,就是我们所说的十进制数也好十六进制数也好,归根到底机器都是要把他变为二进制数的,机器也只认识二进制数,这样你就好理解了,我们不会处理不同进制数之间的运算,运算时必须要把他转换同进制的数,机器也是这样,只不过我们擅长的是十进制的运算,而机器擅长的是二进制运算,二进制数位数多不方便我们就找了一个帮手十六进制数

希望你能看得懂

相关文档
相关文档 最新文档