打印

(新手问前辈)请教如何将N(2以上)字节的HEX转BCD码

[复制链接]
6994|5
手机看帖
扫描二维码
随时随地手机跟帖
沙发
古道热肠| | 2009-12-7 22:26 | 只看该作者
HEX是16进制,将数除10取商,余数再继续,就能得到BCD码了.就象将十进制数变换成二进制一样的,这个好理解了吧.

使用特权

评论回复
板凳
ningling_21| | 2009-12-7 22:35 | 只看该作者
楼上正解...

使用特权

评论回复
地板
白立红雨|  楼主 | 2009-12-8 16:19 | 只看该作者
谢谢回复,还是不理解,比如有三个字节:0x23(高)   0xfd(中)   0x6c(低),怎么换算才能得到2358636,让数码管显示出来呢?

使用特权

评论回复
5
teddeng| | 2009-12-8 17:56 | 只看该作者
本帖最后由 teddeng 于 2009-12-8 18:00 编辑

一定要养成先搜索再提问的习惯,对你自己有好处。


转自http://www.xiao-qi.com/netfile/hextobcd.html  

Hex to bcd转换的算法比较 作者[晓奇]©
--- 晓奇工作室---

C语言主程序部分
// 左移移位法作hex to bcd转换的算法程序,加上这一段调用演示,以察看运行结果
// 12M晶振时汇编算法运行时间大约为1339ns,C语言减法转换时间大约897ns
// 不同的输入数据在C语言的减法转换时间略有不同,最大时间59999时为1231ns
// 所以C语言的减法运算还是略快一些。
// http://www.xiao-qi.com/晓奇工作室收集整理,Keil C51下调试运行通过

#include <reg51.h>

unsigned char bcdData[3];
unsigned int ihexs;
unsigned char disp_buffer[5];

extern void hex_bcd(unsigned int iHex);     // 声明外部函数
void hextobcd(unsigned int hexs,unsigned char j);

void main(void){
    ihexs = 59999;
    hex_bcd(ihexs);
    hextobcd(ihexs,5);
    while(1);
}
   
/***************************
   hex to bcd 转换程序
***************************/
void hextobcd(unsigned int hexs,unsigned char j) {

unsigned int va;
unsigned char i;
    va = 10000;                             //最大数级万位
    for     (i=j-1;i;i--) {
        disp_buffer = 0;                 //目标数组清零
        while ((hexs>=va)&&(va>9)) {
            hexs -= va;                     //减除数
            disp_buffer++;               //商位加1
        }
        va /= 10;                           //除数除10,指向低一位
    }
    disp_buffer[0]=hexs;                    //最后个位数
}

汇编语言模块,建立另一个文件
NAME HEX_BCD
;*************************************************************************
; Hex to 压缩BCD码的转换(每4位代表一位bcd码)
; 输入Hex:R6R7     返回地址:bcdData
;*bcdData = BCD(R6R7)
; http://www.xiao-qi.com/晓奇工作室收集整理,Keil C51下调试运行通过
;*************************************************************************
?PR?_HEX_BCD?HEX_BCD SEGMENT CODE   ; 码段定义叙述,需要对本文件内的所有
?PR?_BCD_ADJ?HEX_BCD SEGMENT CODE   ; 码段定义叙述,需要对本文件内的所有
PUBLIC _HEX_BCD
EXTRN   DATA(bcdData)

RSEG  ?PR?_HEX_BCD?HEX_BCD
_HEX_BCD:CLR     A                   ;目标数据清零初始化
        MOV     bcdData, A
        MOV     bcdData+1, A
        MOV     bcdData+2, A
        MOV     R2, #15             ; 共进行15次循环移位运算
H_B0:   MOV     A, R7               ; 低8位
        RLC     A                   ; 大循环左移
        MOV     R7, A               ; 回存
        MOV     A, R6               ; 高8位
        RLC     A                   ; 大循环左移
        MOV     R6, A               ; 回存。至此已获得当前数据的最高位

        MOV     A, bcdData+2        ; 目标数最低8位
        RLC     A                   ; 移入原数据的最高位
        ACALL   _BCD_ADJ            ; 压缩BCD码的十进制调整
        MOV     bcdData+2, A        ; 存回
        MOV     A, bcdData+1        ; 目标数中间8位
        RLC     A                   ; 移入进位位
        ACALL   _BCD_ADJ            ; 压缩BCD码的十进制调整
        MOV     bcdData+1, A        ; 存回
        MOV     A, bcdData          ; 目标数最高8位
        RLC     A                   ; 移入进位位
        ACALL   _BCD_ADJ            ; 压缩BCD码的十进制调整
        MOV     bcdData, A          ; 存回
        DJNZ    R2, H_B0            ; 继续下一轮循环

; 目标数据再左移一位,将原数据的最后一位放入,这样总共进行了16次循环移位
        MOV     A, R6
        RLC     A
        MOV     A, bcdData+2
        RLC     A
        MOV     bcdData+2, A
        MOV     A, bcdData+1
        RLC     A
        MOV     bcdData+1, A
        MOV     A, bcdData
        RLC     A
        MOV     bcdData, A
        RET

;*************************************************************************
; 压缩BCD码的十进制调整,基本思路:逢十进一,在这里因为还保留着最后一次左
; 移, 所以进位判别的0AH(0A0H)变成相对右移了一位的05H(050H), 而强迫进行进位
; 的方法是加上一个数字3(左移一位后就是6)。程序保护PSW
; 输入返回均使用Acc累加器
;*************************************************************************
RSEG  ?PR?_BCD_ADJ?HEX_BCD

_BCD_ADJ:
    PUSH    PSW
        PUSH    ACC
        CJNE    A, #50H, $+3    ; 高4位。做一个比较产生状态标志
        JC      B1              ; 如果小于#50H, 不用进位处理
        POP     ACC             ; 取原数据作修改
        ADD     A, #30H         ; 加上#30h,留待下一轮左移时产生进位
        PUSH    ACC             ; 存回原数据
  B1:   ANL     A, #0FH         ; 仅考虑低4位
        CJNE    A, #5, $+3      ; 做一个比较产生状态标志
        JC      B2              ; 如果小于#5H, 不用进位处理
        POP     ACC             ; 取原数据作修改
        ADD     A, #3           ; 加上#3h,留待下一轮左移时产生进位
        PUSH    ACC             ; 存回原数据
  B2:   POP     ACC             ; 恢复现场
        POP     PSW
        RET
end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
[nobody]©的快速算法,速度更快。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
?PR?_HEX_BCD?HEX_BCD SEGMENT CODE         
PUBLIC _HEX_BCD
RSEG  ?PR?_HEX_BCD?HEX_BCD
_HEX_BCD:
        CLR     A           ;BCD码初始化
        MOV     R3,A
        MOV     R4,A
        MOV     R5,A
        MOV     R2,#10H     ;转换双字节十六进制整数
HB3:
        MOV     A,R7        ;从高端移出待转换数的一位到CY中
        RLC     A
        MOV     R7,A
        MOV     A,R6
        RLC     A
        MOV     R6,A
        MOV     A,R3        ;BCD码带进位自身相加,相当于乘2
        ADDC    A,R3
        DA      A           ;十进制调整
        MOV     R3,A
        MOV     A,R4
        ADDC    A,R4
        DA      A
        MOV     R4,A
        MOV     A,R5
        ADDC    A,R5
        MOV     R5,A        ;双字节十六进制数的万位数不超过6,不用调整
        DJNZ    R2,HB3      ;处理完16bit
        mov     a,r3
        mov     r7,a
        mov     a,r4
        mov     r6,a
        mov     r4,#0
        RET
end

调用方法:
extern unsigned int hex_bcd(unsigned int iHex);     /*声明外部函数*/

extern unsigned long hex_bcd(unsigned int iHex);    /*声明外部函数*/

使用特权

评论回复
6
wangsheng1997| | 2011-8-26 09:37 | 只看该作者
我很疑问,为什么HEX to BCD的算法看起来和十进制数转BCD一样呢?这个是我不能理解的,本身十进制和十六进制数是不等的呀!望解答

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝