汇编子程序模块:
NBYTE_BCD.asm- ;========================================================================
- ; extern void NBYTEBCD(unsigned char idata *pri, unsigned char leni, unsigned char idata *pro, unsigned char leno);
- ;
- ; N字节无符号二进制 对应 十进制BCD码字节数
- ; (N <= 4 ) 则 N+1
- ; (N <= 9 ) 则 N+2
- ; (N <= 12) 则 N+3
- ; ……
- $NOMOD51
-
- NAME NBYTE_BCD ;模块名
-
- ?PR?_NBYTEBCD?NBYTE_BCD SEGMENT CODE ;在程序存储区中定义段
- ?DT?_NBYTEBCD?NBYTE_BCD SEGMENT DATA OVERLAYABLE
- PUBLIC ?_NBYTEBCD?BYTE
- PUBLIC _NBYTEBCD ;用PUBLIC 声明函数为公共函数
-
- RSEG ?DT?_NBYTEBCD?NBYTE_BCD
- ?_NBYTEBCD?BYTE:
- pri?040: DS 1 ;R7
- leni?041: DS 1 ;R5
- pro?042: DS 1 ;R3
- ORG 3
- leno?043: DS 1
- RSEG ?PR?_NBYTEBCD?NBYTE_BCD ;用RSEG 表示函数可被连接器放置在任何地方
-
- ;========================================================================
- ;函数:N字节无符号二进制转十进制BCD码
- ;输入:*pri
- ;输出:*pro
- ;资源:ACC、CY、R0、R1、R3、R4、R5、R7、leno?043
- ; ROM:59B(包括调用函数时的形参输入)
-
- _NBYTEBCD:
- ;USING 0
- MOV A,R7
- ADD A,R5
- DEC A
- MOV R7,A
-
- MOV A,leno?043
- MOV R4,A
- ADD A,R3
- DEC A
- MOV R3,A
-
- MOV R0,A
- NP__0:
- MOV @R0,#0
- DEC R0
- DJNZ R4,NP__0
-
- MOV A,R5 ;转换(R5)字节二进制整数
- RL A
- RL A
- RL A
- MOV R1,A ;计数器
- CLR C
- NP__1:
- MOV A,R5
- MOV R4,A ;循环(R5)次
- MOV A,R7
- MOV R0,A
- NP__2:
- MOV A,@R0 ;从高端移出待转换数的1位到CY中
- RLC A
- MOV @R0,A
- DEC R0
- DJNZ R4,NP__2
-
- MOV A,leno?043
- MOV R4,A ;循环(leno)次
- MOV A,R3
- MOV R0,A
- NP__3:
- MOV A,@R0 ;BCD码带进位自身相加,相当于乘2
- ADDC A,@R0
- DA A ;十进制调整
- MOV @R0,A
- DEC R0
- DJNZ R4,NP__3
-
- DJNZ R1,NP__1
-
- RET
-
- END
复制代码使用方法,将
NBYTE_BCD.asm 添加到工程中,在
main.c 中声明后就可以调用,举例:
- unsigned char asc[8] = {0x0A,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
- unsigned char nz[10];
-
- extern void NBYTEBCD(unsigned char idata *pri, unsigned char leni, unsigned char idata *pro, unsigned char leno);
-
- void main(void)
- {
- NBYTEBCD(asc, 8, nz, 10);
-
- while (1)
- {
-
- }
- }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
- #include <STRING.H>
- uchar Data[]= {0x0A,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
- uchar BCD[]={0};
- uchar Four_Bit_BCD (uchar Data)
- {
- uchar Data_Temp ;
- switch (Data)
- {
- case 0 : Data_Temp = 0x00 ; break ;
- case 1 : Data_Temp = 0x01 ; break ;
- case 2 : Data_Temp = 0x02 ; break ;
- case 3 : Data_Temp = 0x03 ; break ;
- case 4 : Data_Temp = 0x04 ; break ;
- case 5 : Data_Temp = 0x05 ; break ;
- case 6 : Data_Temp = 0x06 ; break ;
- case 7 : Data_Temp = 0x07 ; break ;
- case 8 : Data_Temp = 0x08 ; break ;
- case 9 : Data_Temp = 0x09 ; break ;
- default : break ;
- }
- return Data_Temp ;
- }
- void Data_Change_BCD(uchar *Data_P,uchar *BCD_P)
- {
- uchar i ;
- uchar Data_Temp_L,Data_Temp_H;
- i=strlen(Data_P);
- for (; i>0; i--)
- {
- Data_Temp_L = *Data_P % 10 ;
- Data_Temp_H = *Data_P / 10 ;
- *BCD_P = Four_Bit_BCD( Data_Temp_H )<<4+Four_Bit_BCD( Data_Temp_L );
- Data_P++;
- BCD_P++ ;
- }
- }
复制代码好像不对头,比如:
十六进制0xFF = 十进制255,将 十六进制0xFF 转换成 BCD 结果应该是 0x0225
十六进制0x0FFF FFFF FFFF FFFF = 十进制1,152,921,504,606,846,975,将 十六进制0x0FFF FFFF FFFF FFFF 转换成 BCD 结果应该是 0x01152921504606846975
BCD码不是用4位的二进制数表示1位的十进制数中的0-9吗?那么一个8位二进制数就是只可以表示0-99咯!
那为什么有0xAA的数据的。不明白,跟帖弄个究竟.理解错,我再想想!
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字节十六进制
哦,原来是这样,好复杂呀,不过我在keil51中用过double型数据修饰符,为什么编译器没有报错的。运算正确奇怪!
一周热门 更多>