转自大虾网 http://www.daxia.com/list_1683.shtml
有一个矛盾总是在困扰我们---那就是计算机喜欢2进制(16进制)而人类已经习惯了10进制
传统的HEX--BCD通常都按二进制定义按权展开,再付以10进制调整来实现,速度太慢,效率低
我的思路是这样的2的12次方=4096=4100-4=1000H及每一个1000H可以看着"4100"如果有误
差可以从余数中扣除,如双字节数最多扣除16*4=64个,如果有余数,够扣就扣,不够扣从4100
个中次高位减一当100已经够了!如果你问16是怎么来得我告诉65536/4096=16下面是程序
DPTR中是待转换的双字节16进制数,转换的数据保存在34H33H32H31H30H五个连续单元中34H
为高,同样的道理把100=60H+4 4096/96最多商42 4*42=168
16=4096/256 64和128因为都是单字节所以运算非常简单,经过仿真对比其运行速度比传统
方式快12倍!!!!!!!
HEXBCD:MOV A,DPH ;16进制高位送A
ANL A,#0F0H ;屏蔽A低四位
XRL DPH,A ;屏蔽DPH高四位
SWAP A ;A除以16 ( 注意这技巧)
MOV 32H,A ;把A个100放百位单元
RL A
RL A ;两次RL A相当于乘以4,这个4表示4A个千,也表示要扣除4A
;A*4096=A*(4000+100)-4A=4A*1000+A*100-4A
XCH A,DPL
SUBB A,DPL
XCH A,DPH
SUBB A,#00H ;以上四条指令完成4A的扣除,结果高位在A,低位在DPH
JNC "够扣"
DEC 32H ;不够扣32H减一当百
MOV A,#101 ;本来是100这里用101是考虑C=1这样就节省一条指令CLR C
SUBB A,DPL
ADD A,DPH ;A肯定小于64为什么?所以高位不计算了!
MOV B,#10
DIV AB
MOV 31H,A
MOV 30H,B
这是个简易的printf,一次只能带一个参数,printf代码在下面。
============================================================
这里是main.c
============================================================
#define _X
#include<myprintf.c> //mypr换成printf时,将此项注释掉
//mypr换成printf时,包含下面三项
//#include<regx52.h> //mypr换成printf时,包外含这三项,将上面一项注释掉
//#include<inituart.c>
//#include<stdio.h>
main()
{
unsigned int k=0x1234;
InitUart();
while(1)
{
mypr("Hello World!
K is %x",k);//定义_U时%x换成%u,用printf时用%u和%x各一次
}
}
void uart(void) interrupt 4 using 0
{
}
#define _X Program Size: data=15.0 xdata=0 code=256
#define _U Program Size: data=27.0 xdata=0 code=716
printf ...一样
%x Program Size: data=32.1 xdata=0 code=1131
%u Program Size: data=32.1 xdata=0 code=1131
============================================================
下面是myprintf.c
============================================================
#include<regx52.h>
#ifndef BaudRate
#define BaudRate 57600L
#endif
#ifndef OSC
#define OSC 22118400L //11.0592M
#endif
#include<inituarts.c>
#ifndef _X
#ifndef _U
#define _X
#define _U
#endif
#endif
unsigned char code hex2ascii[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
//putchar
void prc(unsigned char c)
{
while(!TI)
;
TI=0;
SBUF=c;
}
//xu=1 或2 说明包含输出%u功能
#ifdef _U
void Hex2BCD(unsigned char *p,unsigned int t)
{
unsigned char i=0;
unsigned char s;
if(t<10000) goto ca0;
if(t>=40000) {i =4;t-=40000;} //如果t<=9999,则这部分可不用。
if(t>=20000) {i+=2;t-=20000;}
if(t>=10000) {i++; t-=10000;}
*p++=i+48; //LCDascii
i=0;
ca0:
if(t>=8000) {i =8;t-=8000;goto ca1;}
else
if(t>=4000) {i=4;t-=4000;}
else ;
if(t>=2000) {i+=2;t-=2000;}
ca1:
if(t>=1000) {i++; t-=1000;}
*p++=i+48;
i=0;
if(t>=800) {i =8;t-=800;goto cb1;}
else
if(t>=400) {i=4;t-=400;}
else ;
if(t>=200) {i+=2;t-=200;}
cb1:
s=(unsigned char)t;
if(s>=100) {i++; s-=100;}
*p++=i+48;
i=0;
if(s>=80) {i=8;s-=80;goto cc1;}
else
if(s>=40) {i=4;s-=40;}
else ;
if(s>=20) {i+=2;s-=20;}
cc1:
if(s>=10) {i++; s-=10;}
*p++=i+48;
*p++=s+48;
*p=' ';
}
#endif
//miniprintf
void mypr(unsigned char code *p,unsigned int ap)
{
unsigned char* apbufp;
#ifdef _U
unsigned char apbuf[6];
#endif
for( ;(*p) != ' ';++p)
{
if(*p!='%')
{
prc(*p);
continue;
}
p++;
#ifdef _X
if(*p=='x')
{
prc('0');
prc('x');
apbufp=(unsigned char *)(&ap); //指向ap的高位,简化除法。(只用高位)
while(ap)
{
if(ap&0xf000) //说明ap>0x1000
prc(hex2ascii[(unsigned char)(*apbufp>>4)]); //提取高位,然后除8 ,如0x1234提出0x12,0x12>>4=0x01
else
prc('0');
ap<<=4; //向高位移4位,0x1234变成0x2340变成0x3400变成0x4000变成0x0000
}
}
continue;
#endif
#ifdef _U
if(*p=='u')
{
Hex2BCD(apbuf,ap); //变成BCD数组
apbufp=apbuf;
while(*apbufp)
{
prc(*apbufp);
apbufp++;
}
}
#endif
continue;
}
}
原作者:DENGM
;R2R3-->R5R6R7 小端
BIN2BCD:
MOV A, R3
ANL A, #0FCH
RR A
RR A
MOV R5,A
ADD A, R5
ADD A, R5
MOV R7,A
MOV A, R2
ANL A, #3
MOV R6,A
XRL A, R3
ANL A, #3
XRL A, R2
RR A
RR A
ADD A, R7
JNC L2
INC R5
ADD A, #6
L2: ADD A, R7
MOV B, #25
JNC L3
INC R5
ADD A, #6
DIV AB
SJMP L4
L3: DIV AB
CJNE A, #10, L4
INC R5
CLR A
L4: MOV R7,A
MOV A, #10
XCH A, B
ADD A, #(L5-$-3)
MOVC A, @A+PC
ADD A, R6
DA A
XCH A, R5
DIV AB
XCH A, R7
SWAP A
ORL A, B
SWAP A
MOV R6,A
RET
L5: DB 00H, 04H, 08H, 12H, 16H
DB 20H, 24H, 28H, 32H, 36H
DB 40H, 44H, 48H, 52H, 56H
DB 60H, 64H, 68H, 72H, 76H
DB 80H, 84H, 88H, 92H, 96H
END
r3 r2 r7 r6 r5
一周热门 更多>