关于HEX转换为BCD码的一些理解
二进制与BCD码转换资料

16位二进制数转换成BCD码的的快速算法-51单片机2010-02-18 00:43在做而论道上篇博文中,回答了一个16位二进制数转换成BCD码的问题,给出了一个网上广泛流传的经典转换程序。
程序可见:/%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!.近来,在网上发现了一个链接:/news/Article/uc/uc8051/200803/4751.html,也对这个经典转换程序进行了改进,话是说了不少,只是没有实质性的东西。
这篇文章提到的程序,一直也没有找到,也难辩真假。
这篇文章好像是选自某个著名杂志,但是在术语的使用上,有着明显的漏洞,不像是专业人员的手笔。
比如说文中提到的:“使用51条指令代码,但执行这段程序却要耗费312个指令周期”,就是败笔。
51条指令代码,真不知道说的是什么,指令周期是因各种机型和指令而异的,也不能表示确切的时间。
.下面说说做而论道的编程思路。
;-----------------------------------------------------------------------;已知16位二进制整数n以b15~b0表示,取值范围为0~65535。
BCD码、十六进制与十进制互转

BCD码、十六进制与十进制互转•在做嵌入式软件的设计中,经常会遇到十六进制、BCD码与十进制之间的转换,最近做M1卡的应用中,涉及了大量的十六进制、BCD码与十进制之间的转换。
笔者通过对BCD码、十六进制权的理解,轻松的实现了他们之间的互换。
#include <stdio.h>#include <string.h>/////////////////////////////////////////////////////////功能:二进制取反////输入:const unsigned char *src 二进制数据// int length 待转换的二进制数据长度////输出:unsigned char *dst 取反后的二进制数据////返回:0 success////////////////////////////////////////////////////////int convert(unsigned char *dst, const unsigned char *src, int length) {int i;for(i=0; i<length; i++){dst[i] = src[i]^0xFF;}return 0;}//////////////////////////////////////////////////////////////功能:十六进制转为十进制////输入:const unsigned char *hex 待转换的十六进制数据// int length 十六进制数据长度////输出:////返回:int rslt 转换后的十进制数据////思路:十六进制每个字符位所表示的十进制数的范围是0 ~255,进制为256 // 左移8位(<<8)等价乘以256///////////////////////////////////////////////////////////unsigned long HextoDec(const unsigned char *hex, int length){int i;unsigned long rslt = 0;for(i=0; i<length; i++){rslt += (unsigned long)(hex[i])<<(8*(length-1-i));}return rslt;}///////////////////////////////////////////////////////// ////功能:十进制转十六进制////输入:int dec 待转换的十进制数据// int length 转换后的十六进制数据长度////输出:unsigned char *hex 转换后的十六进制数据////返回:0 success////思路:原理同十六进制转十进制////////////////////////////////////////////////////////// int DectoHex(int dec, unsigned char *hex, int length){int i;for(i=length-1; i>=0; i--){hex[i] = (dec%256)&0xFF;dec /= 256;}return 0;}///////////////////////////////////////////////////////// ////功能:求权////输入:int base 进制基数// int times 权级数////输出:////返回:unsigned long 当前数据位的权//////////////////////////////////////////////////////////// unsigned long power(int base, int times){int i;unsigned long rslt = 1;for(i=0; i<times; i++)rslt *= base;return rslt;}/////////////////////////////////////////////////////////////功能:BCD转10进制////输入:const unsigned char *bcd 待转换的BCD码// int length BCD码数据长度////输出:////返回:unsigned long 当前数据位的权////思路:压缩BCD码一个字符所表示的十进制数据范围为0 ~ 99,进制为100 // 先求每个字符所表示的十进制值,然后乘以权////////////////////////////////////////////////////////// unsigned long BCDtoDec(const unsigned char *bcd, int length){int i, tmp;unsigned long dec = 0;for(i=0; i<length; i++){tmp = ((bcd[i]>>4)&0x0F)*10 + (bcd[i]&0x0F);dec += tmp * power(100, length-1-i);}return dec;}/////////////////////////////////////////////////////////////功能:十进制转BCD码////输入:int Dec 待转换的十进制数据// int length BCD码数据长度////输出:unsigned char *Bcd 转换后的BCD码////返回:0 success////思路:原理同BCD码转十进制//////////////////////////////////////////////////////////// int DectoBCD(int Dec, unsigned char *Bcd, int length){int i;int temp;for(i=length-1; i>=0; i--){temp = Dec%100;Bcd[i] = ((temp/10)<<4) + ((temp%10) & 0x0F);Dec /= 100;}return 0;}int main(){register int i;unsigned char tmp_bff[12] = "";//十六进制转十进制unsigned char HEX[4] = {0x34, 0xFE, 0x3E, 0xFF};unsigned long dec_hex = 0;dec_hex = HextoDec(HEX, 4);printf("dec_hex = %d\n", dec_hex);//十进制转十六进制DectoHex(dec_hex, tmp_bff, 4);for(i=0; i<5; i++){printf("tmp_bff[%d] = 0x%02X\n",i, tmp_bff[i]);}//BCD码转十进制unsigned long dec_bcd = 0;unsigned char BCD[4] = {0x98, 0x23, 0x45, 0x78};dec_bcd = BCDtoDec(BCD, 4);printf("dec_bcd = %d\n", dec_bcd);//十进制转BCD码DectoBCD(dec_bcd, tmp_bff, 4);for(i=0; i<5; i++){printf("tmp_bff[%d] = 0x%02X\n", i, tmp_bff[i]);}getchar();}如果有其他的方法可以一起讨论。
ASCII码、HEX、字符、BCD等等基础知识思考

ASCII码、HEX、字符、BCD等等基础知识思考每每遇到这些问题就要想个半天,想不明⽩还不舒服,今天特别把所想整理下避免以后再次进⼊思想漩涡计算机存储和传输都是以字节为单位1 bit = 1 ⼆进制数据1 byte = 8 bit1 字母 = 1 byte = 8 bit1 汉字 =2 byte = 16 bit1. bit:位⼀个⼆进制数据0或1,是1bit;2. byte:字节存储空间的基本计量单位,如:MySQL中定义 VARCHAR(45) 即是指 45个字节;1 byte = 8 bit3. ⼀个英⽂字符占⼀个字节;1 字母 = 1 byte = 8 bit4. ⼀个汉字占2个字节;1 汉字 =2 byte = 16 bit5. 标点符号A>. 汉字输⼊状态下,默认为全⾓输⼊⽅式;B>. 英⽂输⼊状态下,默认为半⾓输⼊⽅式;C>. 全⾓输⼊⽅式下,标点符号占2字节;D>. 半⾓输⼊⽅式下,标点符号占1字节;故:汉字输⼊状态下的字符,占2个字节 (但不排除,⾃⼰更改了默认设置);英⽂输⼊状态下的字符,占1个字节 (但不排除,⾃⼰更改了默认设置);ASCII码 因为信息在计算机上是⽤⼆进制表⽰的,这种表⽰法让⼈理解就很困难。
因此计算机上都配有输⼊和输出设备,这些设备的主要⽬的就是以⼀种⼈类可阅读的形式将信息在这些设备上显⽰出来供⼈阅读理解。
为保证⼈类和设备,设备和计算机之间能进⾏正确的信息交换,⼈们编制的统⼀的信息交换代码,这就是ASCII码表,它的全称是“美国信息交换标准代码”。
BCD码 BCD码(Binary-Coded Decimal?)亦称⼆进码⼗进数或⼆-⼗进制代码。
⽤4位⼆进制数来表⽰1位⼗进制数中的0~9这10个数码。
是⼀种⼆进制的数字编码形式,⽤⼆进制编码的⼗进制代码。
BCD码这种编码形式利⽤了四个位元来储存⼀个⼗进制的数码,使⼆进制和⼗进制之间的转换得以快捷的进⾏。
码制转换十二进制数ASCII码之间的互相转换BCD

MOV SS,AX
MOV SP,TOP
LEA BX,STRING ;取变量偏址
PUSH BX
;将偏址压栈
PUSH NUM
;将变量压栈
堆栈
AF 25 02 00
0060H 0062H 0064H
26
CALL BINHEX
;(SP)=005EH
CS:0113 LEA DX,STRING ;(DX)=0002H
;若(CL)=0,转NEXT2 ;取字符 ;转换成BCD码 ;加到中间结果上
10
MOV MUL INC JMP NEXT2: MOV AND ADD CMP JNZ NEG NEXT3: MOV RET
DX,10 DX BX SHORT LP1 DL,[BX] DL,0FH AX,DX CH,’-’ NEXT3 AX [DI],AX
(AX)+1000(AX) DL存至缓冲区 令(DL)=0
求100的个数,结构同上
A
(AX)-10
Y
<0?
N
(DL)+1
(AX)+10(AX) 存DL 存AL
返回DOS
15
汇编程序如下:
DATA SEGMENT BNUM DB 270FH DNUM DB 4 DUP(?) ;存放BCD码的缓冲区 DATA ENDS CODE SEGMENT
STR1
0A
02
32
36
0D …
STR2
0A
02
33 33
0D …
NUM
1A
00
21
00
SUM
3B
00
OVER
‘O’
…
…
hex转bcd最快算法

hex转bcd最快算法(实用版)目录1.HEX 转 BCD 的背景和意义2.HEX 转 BCD 的算法原理3.最快算法的实现和优化4.算法的优点和应用场景正文1.HEX 转 BCD 的背景和意义HEX(十六进制)和 BCD(二 - 十进制)是计算机中常用的数制表示方式。
在数字电路和计算机系统中,为了提高数据表示的精度和减少存储空间,常常需要将 HEX 数转换为 BCD 数。
HEX 转 BCD 的算法研究一直是计算机科学领域的热门话题,研究者们致力于寻找更快、更精确的转换算法。
2.HEX 转 BCD 的算法原理HEX 转 BCD 算法的原理是将每一位 HEX 数转换为相应的 BCD 数。
具体来说,每一位 HEX 数都有 4 位二进制表示,而每一位 BCD 数有 10 位二进制表示。
因此,每一位 HEX 数可以转换为两位半的 BCD 数,即 4 位二进制表示可以转换为 10 位二进制表示。
3.最快算法的实现和优化目前,最快的 HEX 转 BCD 算法是基于位运算的算法。
该算法利用位运算的快速和低耗特点,将每一位 HEX 数直接转换为相应的 BCD 数。
具体来说,每一位 HEX 数可以通过以下步骤转换为 BCD 数:- 将 HEX 数的 4 位二进制表示中的每一位与相应的权重相乘,权重分别为 1、2、4 和 8。
- 将乘积相加,得到 BCD 数的 10 位二进制表示。
- 将 10 位二进制表示中的前 6 位保留,后 4 位舍去,得到 BCD 数的 10 位二进制表示。
4.算法的优点和应用场景基于位运算的 HEX 转 BCD 算法具有速度快、精度高和占用资源少等优点。
hex2bcd的c函数

hex2bcd的c函数在编程中,十六进制(hexadecimal)和二进制编码(binary-coded decimal,BCD)是常见的数据表示方式。
在某些特定的场景中,我们可能需要将十六进制转换为BCD格式,这就需要用到一个名为hex2bcd的C函数。
本文将一步一步地回答关于hex2bcd函数的问题,以帮助读者更好地理解和使用这个函数。
第一步:了解hex2bcd函数的基本原理hex2bcd函数的主要作用是将十六进制数转换为BCD格式。
BCD是一种用四位二进制表示一个十进制数字的编码方式。
例如,数字5在BCD中表示为0101,数字12表示为0001 0010。
hex2bcd函数通过位运算和移位操作,将十六进制数的每一位转换为相应的BCD格式。
第二步:理解hex2bcd函数的参数和返回值在C语言中,函数的参数和返回值是非常重要的。
我们首先需要了解hex2bcd 函数所需的参数和返回值。
一般而言,hex2bcd函数通常具有以下形式:uint8_t hex2bcd(uint8_t hex)hex2bcd函数只有一个参数hex,该参数为要转换的十六进制数。
返回值是一个无符号8位整数,表示转换后的BCD数。
第三步:实现hex2bcd函数在了解hex2bcd函数的基本原理和参数后,我们可以开始实现这个函数。
具体的实现方式可能因不同的编程语言而有所不同,这里我们以C语言为例给出一个简单的实现示例:cuint8_t hex2bcd(uint8_t hex) {uint8_t low = hex % 10;uint8_t high = hex / 10;return (high << 4) low;}上述代码中,我们首先通过取模运算得到hex的个位数(low)和十位数(high)。
然后,我们将十位数左移4位,并与个位数进行位运算,最终得到转换后的BCD 数。
第四步:使用hex2bcd函数进行转换编写完hex2bcd函数后,我们可以在实际应用中使用它进行转换。
十六进制数转BCD码的几种方法

十六进制数转BCD码的几种方法1.按位转换法:这种方法是将十六进制数的每一位转换成对应的BCD码。
将每一位数字转换成4位的BCD码,即用0000表示数字0,用0001表示数字1,以此类推,用1001表示数字9、例如,对于十六进制数0x2D,将2转换成0010,将D转换成1101,最终得到的BCD码就是001011012.分离法:这种方法将十六进制数的每一位数字分离出来,然后将每一位数字转换成对应的BCD码。
先将十六进制数分离成两个部分,高位和低位。
例如,对于十六进制数0x2D,高位是2,低位是D。
将2转换成0010,将D转换成1101,最终得到的BCD码就是001011013.ASCII码法:这种方法将十六进制数转换成ASCII码,然后将每个ASCII码转换成对应的BCD码。
每个字符的ASCII码都是8位二进制数,可以将8位二进制数分割成两个4位二进制数,然后将每个4位二进制数转换成对应的BCD码。
例如,对于十六进制数0x2D,将2转换成ASCII码0x32,将D转换成ASCII码0x44,然后将0x32转换成00110010的BCD码,将0x44转换成01000100的BCD码,最终得到的BCD码就是0011001001000100。
4.除2取余法:这种方法将十六进制数除以2,然后求余数,再将余数转换成对应的BCD码。
例如,对于十六进制数0x2D,将它除以2得到21,余数为1,将1转换成0001的BCD码,然后再将21除以2得到10,余数为0,将0转换成0000的BCD码,最终得到的BCD码就是00010000。
以上是几种常见的将十六进制数转换成BCD码的方法。
这些方法都是将十六进制数的每一位数字转换成对应的BCD码,只是实现方式不同。
根据具体的需求和编程环境,可以选择合适的方法进行转换。
BCD码转HEX,HEX转BCD码代码

INT8U result;
INT32U data, i;
//判断data_len的合法性
if (data_len > 5) {
ASSERT_FAILED();
//return 0;
}
//检查BCD数据的合法性
result = CheckBcdData(pdata, data_len);
if (result EQ FALSE) {
i++;
}
}
//+++++++++++++++++++++++++ FUNCTION DESCRIPTION ++++++++++++++++++++++++++++++
//
// NAME : Hex2Bcd_S
//
// DESCRIPTION :有符号数的Hex到BCD的转换
//
// COMPLETION
// INPUT : data pdest dest_len pdest_buf destbuf_len
// OUTPUT :
// STATUS : VOID
//
//-----------------------------------------------------------------------------
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于HEX转BCD码的一些理解1、网上的用51汇编实现的经典方式1)首先是一个网上的经典的51汇编指令实现16bit转换的例子,具体代码如下:2)此代码的原理和分析过程如下:首先解释此段程序功能:入口参数:R6,R7,存放16位二进制数,R6为高8位。
出口参数:R3,R4,R5,存放转换后的BCD码,R3为高位。
程序思路:把16位二进制数按权展开后再进行BCD码相加。
如下图:注意此处加法是按照BCD码相加(代码中有十进制调整指令DA A)。
具体算法:把16位二进制数的每一位都先移入进位标志C,然后乘以2的n次方,这里n是该位的权值。
(此段程序是用与自身相加的方法实现乘2操作的)。
因为共有16位2进制数,所以需要进行16次循环(程序中用R2保存循环次数)。
这样最高位(即R6的最高位)最先被移出并在第一次循环中做了乘2操作并保存在R3R4R5中以供下次累加,第二次循环时该值被再次乘2并累加,以后每次循环都相当于再次进行乘2并累加,这样最高位一共进行了16次乘2累加,也就是乘以2的16次方。
同理,R6的次高位第二次被移出,所以少循环一次,相当于乘以2的15次方并累加。
举例说明:设R6=00H、R7=10H,则R7中的“1”在第12次循环时被移入C中,在以后的4次循环中实现了乘以2的4次方并进行BCD码累加,具体过程如下:R6R7=0000 0000 0001 0000。
R5=R4=R3=0第1次循环:R6最高位的0被移入C标志位后用ADDC指令与R5进行BCD码相加(如有进位则进到R4和R3中,此处无进位),R5=0第2次循环:0被移出后与R5进行BCD码相加,R5=0第3次循环:0被移出后与R5进行BCD码相加,R5=0... ...第11次循环:0被移出后与R5进行BCD码相加,R5=0第12次循环:1被移出后与R5进行BCD码相加,R5=1第13次循环:0被移出后与R5进行BCD码相加,R5=2第14次循环:0被移出后与R5进行BCD码相加,R5=4第15次循环:0被移出后与R5进行BCD码相加,R5=8第16次循环:R7最低位的0被移出后与R5进行BCD码相加,R5=16所以最终结果就是16(放在R5中)。
3)个人对这个代码的理解:a)这段代码执行效率比较高,但需要DA指令,对于某些单片机不支持DA指令需要自己编写DA指令的实现。
b)51汇编指令很多只能对寄存器A操作。
因此循环的格式是MOV A,R6;RLC A; MOV R6,A;对于能直接对其他寄存器执行循环指令的MCU修改后效率更高。
c)DA指令的实现需要辅助进位标志,若MCU无此标志位,则实现起来比较困难。
2、个人改进后的51汇编实现的方式1)基于很多单片机不带有辅助进位标志且没有DA类指令,下面是个人对这个经典算法的改进具体代码如下:DSEG AT 20H ;KEIL汇编51定义寄存器方法。
地址为20H TMP: DS 1 ;中间缓存寄存器,中间变量HEX_U: DS 1 ;HEX_U/H/L存器,3*8bit=24bit,2^24=16777216HEX_H: DS 1HEX_L: DS 1BCD4: DS 1 ;BCD4/3/2/1出口寄存器,因为入口寄存机;最大为:2^24-1=16777215BCD3: DS 1 ;共需要8位BCD码,因此需要4个寄存器用来存放压;缩BCD码BCD2: DS 1BCD1: DS 1COUNT: DS 1 ;中间变量,用来存放移位次数,本例中移位24次BSEG AT 20H ;KEIL汇编51位定义方式LL BIT 3 ;LL=20H.3=TMP.3LH BIT 7 ;LH=20H.7=TMP.7CSEG AT 0000H ;代码段定义起始位置LJMP R_MIANCSEG AT 0010HR_MIAN:HEX_TO_BCD_Init:MOV A,#24MOV COUNT,A ;循环次数24次MOV A,#0XFFMOV HEX_U,A ;HEX数据入口,此处只作赋值验证,MOV HEX_H,A ;若想写成函数在调用函数时将形参赋值即可MOV HEX_L,AMOV A,#00HMOV BCD4,A ;BCD结果初始化赋值为零MOV BCD3,AMOV BCD2,AMOV BCD1,ASHIFT_LOOP:MOV A,HEX_L ;C<---HEX_U/H/L<--RLC A ;|________________|MOV HEX_L,A ;HEX循环左移MOV A,HEX_HRLC AMOV HEX_H,AMOV A,HEX_URLC AMOV HEX_U,AMOV A,BCD1 ;C<---BCD4/3/2/1<--RLC A ;|________________|MOV BCD1,A ;BCD结果循环左移MOV A,BCD2RLC AMOV BCD2,AMOV A,BCD3RLC AMOV BCD3,AMOV A,BCD4RLC AMOV BCD4,ADEC COUNT ;移位次数减一MOV A,COUNTJNZ DA_BCD_Start ;判断是否全部移位完成SJMP $ ;运行完成停在这儿DA_BCD_Start: ;移位后调整结果为十进制BCD码;*********************************************;调整结果为十进制BCD码原理如下:;假如寄存器A,带C循环左移动相当于:B=A+A+C;我们就是要调整B为BCD码,原理详见微机原理的DAA指令;这里只是简单讲一下调整步骤:; 1、若低4位大于9或辅助标志位=1,则将B=B+0X06; 2、在步骤1基础上,若高4位大于9或进位标志=1,则将B=B+0X60 ; 3、进位C算高位;由于我们的单片机没有这个DA类指令,也没有辅助进位标志位;所以对上述原理进行了改进:B=B+0X06<===>B/2=B/2+0X03;因此我们可以再左移位之前进行:低四位加0XO3,高四位加0X30然后再移位;DAA中条件的判断可以这样做:;1、将B寄存器先加0X03,判断B.3是否为1,为1说明条件满足,否则不满足;2、在1基础B寄存器加0X30,判断B.7是否为1,为1说明条件满足,否则不满足;详细代码如下:;*********************************************DA_BCD1_Low4Bit:MOV A,BCD1 ;BCD1+0X03ADD A,#0X03MOV TMP,AJNB LL,DA_BCD1_High4BitMOV BCD1,A ;条件满足BCD0=BCD1+0X03DA_BCD1_High4Bit:MOV A,BCD1 ;BCD1+0X30ADD A,#0X30MOV TMP,AJNB LH,DA_BCD2_Low4BitMOV BCD1,A ;条件满足BCD1=BCD1+0X30DA_BCD2_Low4Bit: ;BCD2调整MOV A,BCD2ADD A,#0X03 ;此处不带进位加因为不可能产生进位,原因如下:MOV TMP,A ;高3位不可能出现111、101、110,假如上次数据是; 0101XXXX(拿这个举例),该数据会调整为1000XXXX,;;移位后本次数据高3位为000,而不是101;因此不会出现BCD1调整后C=1的情况JNB LL,DA_BCD2_High4BitMOV BCD2,ADA_BCD2_High4Bit:MOV A,BCD2ADD A,#0X30MOV TMP,AJNB LH,DA_BCD3_Low4BitMOV BCD2,ADA_BCD3_Low4Bit: ;BCD3调整MOV A,BCD3ADD A,#0X03MOV TMP,AJNB LL,DA_BCD3_High4BitMOV BCD3,ADA_BCD3_High4Bit:MOV A,BCD3ADD A,#0X30MOV TMP,AJNB LH,DA_BCD4_Low4BitMOV BCD3,ADA_BCD4_Low4Bit: ;BCD4调整MOV A,BCD4ADD A,#0X03MOV TMP,AJNB LL,DA_BCD4_High4BitMOV BCD4,ADA_BCD4_High4Bit:MOV A,BCD4ADD A,#0X30MOV TMP,AJNB LH,DA_BCD_EndMOV BCD4,ADA_BCD_End:LJMP SHIFT_LOOPEND2)该代码原理同1中的经典例子,只不过是对其的做了修改,具体不同的细节部分在代码中有详细的注释说明。
此代码已经在KEIL上验证通过,截图如下:3、关于AD指令的一些说明此指令原理同微机原理中的压缩BCD数加法调整指令DAA相同,附件为DAA指令的一些说明。
BCD数调整指令.doc。