实现自己的嵌入式printf函数

本文介绍了如何在嵌入式环境中实现printf函数,以满足串口通信的需求。代码示例提供了对字符串、十进制、十六进制、二进制和浮点数的格式化输出,并在MSP430F149 IAR和VS2008环境下进行了测试。此外,还讨论了参数类型匹配和浮点数精度控制的问题。
摘要由CSDN通过智能技术生成

  做嵌入式开发的朋友都知道,要获取正在调试的代码运行情况的相比PC开发要难得多.首要问题是数据显示的通路少,其次是嵌入式C开发经常发现很多基本的C运行库函数都没有在所使用的平台实现,即使有,也可能庞大得吓人。今天要DIY的就是PC平台使用最广泛的printf函数。参考了部分网上程序,从代码里有注明.

    printf()函数在有的单片机开发环境下往串口发送数据,若你使用的环境恰好有这么个函数功能,那我很羡慕。没有也没关系,今天我们就来实现它这里要介绍实现的printf函数,也是往串口发送数据的,当然,要改变所发送的端口是轻而易举的,后面从代码里就很容易看出来了,实际上,我还在VS2008上模拟了这个函数,其中就将其改成发送到电脑屏幕上。区分标准器printf起见,我们将其命名为myprintf()。

     下面先来看一下函数声明。 

int myprintf(const char *fmt, ...);

这是一个可变参数,不明白的朋友可以Google一下,或在VS帮助文档里检索va_list,va_arg, va_end, va_start都行.

    接下来贴出函数体

/********************************************
*输出到串口
*     只支持以下格式输出:
*     s:字符串
*     d:十进制
*     x:十六进制
*     b:二进制
*     f:默认输出3位精度小数(没有做四舍五入)
*注意:不能转换太大的数/精度要求太高的数,以防溢出错误
*     f:在vs2008中不能通过,
*作者:王桂杰,参考了一个网上程序
********************************************/
int myprintf(const char *fmt, ...)
{
#define DEFAULT_PRECI 3 
    const char *s;
    int value;
    int preci = DEFAULT_PRECI;
    float fdata;
    char buf[16];
    va_list ap;
    va_start(ap, fmt);
    while (*fmt) {
        if (*fmt != '%') {
            term_putc(*fmt++);
            continue;
        }
        switch (*++fmt) {
            case 's':
                s = va_arg(ap, const char *);
                for ( ; *s != '/0'; s++) {
                    //putchar(*s);
                  term_putc(*s);
                }
                break;
            case 'd':                     //Signed decimal integer
                value = va_arg(ap, int);  //不同编译器/CPU位数,类型可能不同,uint8_t,uint16_t,uint32_t等
                itoa(value, buf, 10);
                for (s = buf; *s != '/0'; s++) {
                    //putchar(*s);
                    term_putc(*s);
                }
                break;
            case 'x':                     //Unsigned hexadecimal integer
                value = va_arg(ap, int); 
                term_puts_P("0x");
                term_puthex_byte(value);
                break;
            case 'b':                     //二进制打印
                value = va_arg(ap,int);
                term_putbin_byte(value);
                term_putc('b');
                break;
            case 'f':                     //浮点数输出,默认精度为3位小数
                //fdata = va_arg(ap, float);//MSP430F149(16位CPU),IAR平台可以,
                fdata = va_arg(ap, double);//windows默认存储方式是double类型,使用float将获不到正确结果(vs2008,64位CPU)
                ftoa(fdata, buf, DEFAULT_PRECI);
                for (s = buf; *s != '/0'; s++) {
                    //putchar(*s);
                    term_putc(*s);
                }
                break;  
            case '.':                     //浮点数精度控制
                if(isdigit(*++fmt)){
                  preci = *fmt - '0';
                  if(*++fmt == 'f'){
                    //fdata = va_arg(ap, float);
                    fdata = va_arg(ap, double);
                    ftoa(fdata, buf, preci);
                    for (s = buf; *s != '/0'; s++){
                        //putchar(*s);
                        term_putc(*s);
                    } 
                    break;
                  }
                  preci = DEFAULT_PRECI;
                }
                term_putc(*fmt);
                break;             
          
            /* 在下面增加其他格式 */             
            default: 
                //putchar(*fmt);
                term_putc(*fmt);
#if 0
                s = "UNSURPORT FORMAT!";
                for( ; *s != '/0'; s++){
                    term_putc(*s);
                }
                va_end(ap);
                return 0;
#endif  
        }
        fmt++;
    }
    va_end(ap);
    return 1;   /* Dummy return value */
}

 上面是函数是用于MSP430F149 IAR开发环境的,很用于看出,term_putc即是往单片机串口发送数据的。可想而知,在使用这个函数前应该先初始化串口,抽象出term_putc接口,本文就不涉及这个问题了。下面给出的就是通过#define term_puc    putchar  偷梁换柱,在PC上模拟的程序.

 

/********************************************
*     只支持以下格式输出:
*     s:字符串
*     d:十进制
*     x:十六进制
*     b:二进制
*     f:默认输出3位精度小数
*注意:不能转换太大的数/精度要求太高的数,以防溢出错误
*作者:王桂杰 参考了网上一个程序
********************************************/
#define WINDOWS_VS2008
int myprintf(const char *fmt, ...)
{
#define DEFAULT_PRECI  3 
#ifdef WINDOWS_VS2008
#define term_putc      putchar //用于vs2008测试 
#endif
    const char *s;
    int value;
    int preci = DEFAULT_PRECI;
    float fdata;
    char buf[32];//char buf[16];
    va_list ap;
    va_start(ap, fmt);
    while (*fmt) {
        if (*fmt != '%') {
   //putchar(*fmt++);
            term_putc(*fmt++);
            continue;
        }
        swit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值