?? serial.c
字號(hào):
return;
}
else if(ch=='\n'){PrintChar(10);PrintChar(13);}
else if(ch=='\t'){
for(j=0;j<TABNum;j++)
PrintChar(' ');
}
else PrintChar(ch);
}
ch=*fmt++;
switch(ch){
case 'c':
PrintChar(*((char *)p));
p=(char *)p+1;
break;
case 'd':
PrintN(*((int *)p),10);
p=(int *)p+1;
break;
case 'x':
PrintN(*((int *)p),16);
p=(int *)p+1;
break;
case 'o':
PrintUN(*((int *)p),8);
p=(int *)p+1;
break;
case 'b':
PrintUN(*((int *)p),2);
p=(int *)p+1;
break;
case 'l':
ch=*fmt++;
switch(ch){
case 'd':
PrintLN(*((long *)p),10);
p=(long *)p+1;
break;
case 'o':
PrintLUN(*((long *)p),8);
p=(long *)p+1;
break;
case 'u':
PrintLUN(*((unsigned long *)p),10);
p=(unsigned long *)p+1;
break;
case 'b':
PrintLUN(*((long *)p),2);
p=(long *)p+1;
break;
case 'x':
PrintLN(*((long *)p),16);
p=(long *)p+1;
break;
default:
//出臨界區(qū)
#pragma ASM
POP IE;
#pragma ENDASM
return;
}
break;
case 'f':
DispF(*((float *)p));
p=(float *)p+1;
break;
case 'u':
PrintUN(*((unsigned int *)p),10);
p=(unsigned int *)p+1;
break;
case 's':
PrintStr(*((char **)p));
p=(char **)p+1;
break;
case '%':
PrintChar('%');
p=(char *)p+1;
break;
default:
//出臨界區(qū)
#pragma ASM
POP IE;
#pragma ENDASM
return;
}
}
}
void PrintN(int n,int b) reentrant //十進(jìn)制顯示整形數(shù)
{
if(b==16){PrintWord(n);return;}
if(n<0){PrintChar('-');n=-n;}
if(n/b)
PrintN(n/b,b);
PrintChar(n%b+'0');
}
void PrintUN(unsigned int n,unsigned int b) reentrant //十進(jìn)制顯示無(wú)符號(hào)整形數(shù)
{
if(b==16){PrintWord(n);return;}
if(n/b)
PrintUN(n/b,b);
PrintChar(n%b+'0');
}
void PrintLN(long n,long b) reentrant //十進(jìn)制顯示長(zhǎng)整形數(shù)
{
if(b==16){PrintLong(n);return;}
if(n<0){PrintChar('-');n=-n;}
if(n/b)
PrintLN(n/b,b);
PrintChar(n%b+'0');
}
void PrintLUN(unsigned long n,unsigned long b) reentrant //十進(jìn)制顯示無(wú)符號(hào)長(zhǎng)整形數(shù)
{
if(b==16){PrintLong(n);return;}
if(n/b)
PrintLUN(n/b,b);
PrintChar(n%b+'0');
}
//============================================================================================
//KEIL C51的float類(lèi)型采用IEEE-754標(biāo)準(zhǔn)存儲(chǔ),占4字節(jié)。
// S E E E E E E E E E (1) M M M M M M M M M M M M M M M M M M M M M M M
// S 1bit 正負(fù)標(biāo)志位0=正;1=負(fù)
// E 8bit 二進(jìn)制階碼=(EEEEEEEE)-127
// M 23bit 24bit尾數(shù),只存儲(chǔ)23位,最高位固定為1。此方法用最較少的位數(shù)實(shí)現(xiàn)了較高的有效數(shù),提高了精度。
//
// 尾數(shù)為24bit,最高可表達(dá)的整數(shù)值為2^24-1=16777215,也就是說(shuō),小于等于16777215的整數(shù)可以被精確
//顯示。這決定了十進(jìn)制浮點(diǎn)數(shù)的有效位數(shù)為7位,10^7<16777215<10^8,10的7次方以?xún)?nèi)的數(shù)小于16777215,
//可以精確表示。使用科學(xué)記數(shù)法時(shí),整數(shù)部分占1位,所以小數(shù)部分最大占7-1=6位,即最大有6位精度。
// 長(zhǎng)整形數(shù)和浮點(diǎn)數(shù)都占4字節(jié),但表示范圍差別很大。浮點(diǎn)數(shù)的范圍為+-1.175494E-38到+-3.402823E+38,
//無(wú)符號(hào)長(zhǎng)整形數(shù)范圍為0到4294967295。顯示浮點(diǎn)數(shù)要用到長(zhǎng)整形數(shù)保存數(shù)據(jù),可他們范圍差這么多,怎么辦呢?
// 仔細(xì)觀(guān)察十進(jìn)制浮點(diǎn)數(shù)的顯示,有一個(gè)尾數(shù)和一個(gè)階碼,由上面論證可知32位浮點(diǎn)數(shù)最大有效數(shù)字為7位十進(jìn)制
//數(shù),超出此范圍的數(shù)字有截?cái)嗾`差,不必理會(huì),因此,使浮點(diǎn)數(shù)尾數(shù)能夠放在長(zhǎng)整形數(shù)里保存。階碼為-38到38,
//一個(gè)char型變量就可以保存。
// 綜上所述,以10^7的最大跨度為窗口(小于10^7也可以,如:10,100...10000等,但決不能大于它,那樣會(huì)
//超出精度范圍),定位浮點(diǎn)數(shù)的量級(jí),然后取出7位尾數(shù)的整數(shù)值,再調(diào)整階碼,就可以精確顯示此浮點(diǎn)數(shù)。
// 量級(jí)尺度如下:
// (-38)-(-35)-(-28)-(-21)-(-14)-(-7)-(0)-(7)-(14)-(21)-(28)-(35)-(38)
// 請(qǐng)嚴(yán)格按照KEIL手冊(cè)給出的浮點(diǎn)數(shù)范圍顯示,因?yàn)閿?shù)值空間沒(méi)有完全使用,有些值用于錯(cuò)誤指示和表示正負(fù)無(wú)窮。
//小于1.175494E-38的數(shù)仍可以顯示一些,但最好不用,以免出錯(cuò)。我采用直接判斷的方法,剔除此種情況。
// 在計(jì)算機(jī)里結(jié)合律不成立,(a*b)*c!=a*(b*c),原則是先讓計(jì)算結(jié)果值動(dòng)態(tài)范圍小的兩個(gè)數(shù)運(yùn)算,請(qǐng)注意程序里
//的寫(xiě)法。
// 注:(1E38/b)*1E6不要寫(xiě)成1E44/b,因?yàn)闊o(wú)法在32位浮點(diǎn)數(shù)里保存1E44,切記!
// 計(jì)算機(jī)使用二進(jìn)制數(shù)計(jì)算,能有效利用電子器件高速開(kāi)關(guān)的特性,而人習(xí)慣于十進(jìn)制數(shù)表示,二進(jìn)制和十進(jìn)制
//沒(méi)有方便的方法轉(zhuǎn)換,只能通過(guò)大量計(jì)算實(shí)現(xiàn),浮點(diǎn)數(shù)的十進(jìn)制科學(xué)記數(shù)法顯示尤其需要大量的運(yùn)算,可見(jiàn),顯示
//一個(gè)浮點(diǎn)數(shù)要經(jīng)過(guò)若干次浮點(diǎn)運(yùn)算,沒(méi)有必要就不要顯示,花在顯示上的時(shí)間比計(jì)算的耗時(shí)都要多得多。
//============================================================================================
void DispF(float f) reentrant //用科學(xué)記數(shù)法顯示浮點(diǎn)數(shù),在float全范圍內(nèi)精確顯示,超出范圍給出提示。
{ //+-1.175494E-38到+-3.402823E+38
float tf,b;
unsigned long w;
char i,j;
if(f<0){
PrintChar('-');
f=-1.0*f;
}
if(f<1.175494E-38){
yyprintf("?.??????");//太小了,超出了最小范圍。
return;
}
if(f>1E35){ //f>10^35
tf=f/1E35;
b=1000.0;
for(i=0,j=38;i<4;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(1E29*b); //1E35*b/1E6
PrintW(w,j);
}
else if(f>1E28){ //10^28<f<=10^35
tf=f/1E28;
b=1E7;
for(i=0,j=35;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(1E22*b); //1E28*b/1E6
PrintW(w,j);
}
else if(f>1E21){ //10^21<f<=10^28
tf=f/1E21;
b=1E7;
for(i=0,j=28;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(1E15*b); //1E21*b/1E6
PrintW(w,j);
}
else if(f>1E14){ //10^14<f<=10^21
tf=f/1E14;
b=1E7;
for(i=0,j=21;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(1E8*b); //1E14*b/1E6
PrintW(w,j);
}
else if(f>1E7){ //10^7<f<=10^14
tf=f/1E7;
b=1E7;
for(i=0,j=14;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(10.0*b); //1E28*b/1E6
PrintW(w,j);
}
else if(f>1){ //1<f<=10^7
tf=f;
b=1E7;
for(i=0,j=7;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f/(1E-6*b); //1E0*b/1E6
PrintW(w,j);
}
else if(f>1E-7){ //10^-7<f<=1
tf=f*1E7;
b=1E7;
for(i=0,j=0;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E13/b); //(1E7/b)*1E6
PrintW(w,j);
}
else if(f>1E-14){ //10^-14<f<=10^-7
tf=f*1E14;
b=1E7;
for(i=0,j=-7;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E20/b); //(1E14/b)*1E6
PrintW(w,j);
}
else if(f>1E-21){ //10^-21<f<=10^-14
tf=f*1E21;
b=1E7;
for(i=0,j=-14;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E27/b); //(1E21/b)*1E6
PrintW(w,j);
}
else if(f>1E-28){ //10^-28<f<=10^-21
tf=f*1E28;
b=1E7;
for(i=0,j=-21;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E34/b); //(1E28/b)*1E6
PrintW(w,j);
}
else if(f>1E-35){ //10^-35<f<=10^-28
tf=f*1E35;
b=1E7;
for(i=0,j=-28;i<8;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E35/b)*1E6; //(1E35/b)*1E6
PrintW(w,j);
}
else{ //f<=10^-35
tf=f*1E38;
b=1000.0;
for(i=0,j=-35;i<4;i++,j--)
if(tf/b<1) b=b/10.0;
else break;
w=f*(1E38/b)*1E6; //(1E38/b)*1E6
PrintW(w,j);
}
}
void PrintW(unsigned long w,char j) reentrant //科學(xué)記數(shù)法,顯示十進(jìn)制尾數(shù)和階碼。
{
char i;
unsigned long tw,b;
//if(j<-38){yyprintf("?.??????");return;}//太小了,超出最小表數(shù)范圍。
//if(j>38){yyprintf("*.******");return;}此算法不會(huì)出現(xiàn)j>38的情況。
tw=w/1000000;
PrintChar(tw+'0');PrintChar('.');
w=w-tw*1000000;
b=100000;
for(i=0;i<6;i++){
tw=w/b;
PrintChar(tw+'0');
w=w-tw*b;
b=b/10;
}
yyprintf("E%d",(int)j);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -