⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 在别处找到的一些uc/os-ii的一些资料
💻 C
📖 第 1 页 / 共 2 页
字号:
                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:
//出临界区
#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:
//出临界区
#pragma ASM
    POP IE;
#pragma ENDASM
                return;
        }
    }
}

void PrintN(int n,int b) reentrant  //十进制显示整形数
{
    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  //十进制显示无符号整形数
{
    if(b==16){PrintWord(n);return;}
	if(n/b)
	    PrintUN(n/b,b);
	PrintChar(n%b+'0');
}


void PrintLN(long n,long b) reentrant  //十进制显示长整形数
{
    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  //十进制显示无符号长整形数
{
    if(b==16){PrintLong(n);return;}
	if(n/b)
	    PrintLUN(n/b,b);
	PrintChar(n%b+'0');
}

//============================================================================================
//KEIL C51的float类型采用IEEE-754标准存储,占4字节。
//    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    正负标志位0=正;1=负
//  E    8bit    二进制阶码=(EEEEEEEE)-127
//  M   23bit    24bit尾数,只存储23位,最高位固定为1。此方法用最较少的位数实现了较高的有效数,提高了精度。
//
//  尾数为24bit,最高可表达的整数值为2^24-1=16777215,也就是说,小于等于16777215的整数可以被精确
//显示。这决定了十进制浮点数的有效位数为7位,10^7<16777215<10^8,10的7次方以内的数小于16777215,
//可以精确表示。使用科学记数法时,整数部分占1位,所以小数部分最大占7-1=6位,即最大有6位精度。
//  长整形数和浮点数都占4字节,但表示范围差别很大。浮点数的范围为+-1.175494E-38到+-3.402823E+38,
//无符号长整形数范围为0到4294967295。显示浮点数要用到长整形数保存数据,可他们范围差这么多,怎么办呢?
//  仔细观察十进制浮点数的显示,有一个尾数和一个阶码,由上面论证可知32位浮点数最大有效数字为7位十进制
//数,超出此范围的数字有截断误差,不必理会,因此,使浮点数尾数能够放在长整形数里保存。阶码为-38到38,
//一个char型变量就可以保存。
//  综上所述,以10^7的最大跨度为窗口(小于10^7也可以,如:10,100...10000等,但决不能大于它,那样会
//超出精度范围),定位浮点数的量级,然后取出7位尾数的整数值,再调整阶码,就可以精确显示此浮点数。
//  量级尺度如下:
//    (-38)-(-35)-(-28)-(-21)-(-14)-(-7)-(0)-(7)-(14)-(21)-(28)-(35)-(38)
//  请严格按照KEIL手册给出的浮点数范围显示,因为数值空间没有完全使用,有些值用于错误指示和表示正负无穷。
//小于1.175494E-38的数仍可以显示一些,但最好不用,以免出错。我采用直接判断的方法,剔除此种情况。
//  在计算机里结合律不成立,(a*b)*c!=a*(b*c),原则是先让计算结果值动态范围小的两个数运算,请注意程序里
//的写法。
//  注:(1E38/b)*1E6不要写成1E44/b,因为无法在32位浮点数里保存1E44,切记!
//  计算机使用二进制数计算,能有效利用电子器件高速开关的特性,而人习惯于十进制数表示,二进制和十进制
//没有方便的方法转换,只能通过大量计算实现,浮点数的十进制科学记数法显示尤其需要大量的运算,可见,显示
//一个浮点数要经过若干次浮点运算,没有必要就不要显示,花在显示上的时间比计算的耗时都要多得多。
//============================================================================================
void DispF(float f) reentrant  //用科学记数法显示浮点数,在float全范围内精确显示,超出范围给出提示。
{                              //+-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  //科学记数法,显示十进制尾数和阶码。
{
    char i;
    unsigned long tw,b;
    
    //if(j<-38){yyprintf("?.??????");return;}//太小了,超出最小表数范围。
    //if(j>38){yyprintf("*.******");return;}此算法不会出现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);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -