一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 3521|回复: 8
收起左侧

[其他综合] stm8 使用 printf

[复制链接]
发表于 2016-2-22 16:47 | 显示全部楼层 |阅读模式

  小可在使用STM8的时候,喜欢利用自带的UART来做调试,这样的话就可以 下载+调试一条龙了,非常的方便.

  我在 uart1.c 中写了许多的函数,像
  UART1_SendByte()

  UART1_SendStr()

  UART1_SendNum()

  UART1_SendInt()



虽然可以满足大部分的需要,但是在文字和数字结合时就得分别写多个函数,像:
UART1_SendStr("\r\nHello,");
UART1_SendNum( 2016 );
UART1_SendStr( "!" );
看起来不是很好.
于是想到了 printf.

电脑上printf可以打到控制台上,单片机肯定没那么聪明?
在 代码头部加上 #include "stdio.h"
这样就可以使用 printf函数了,网上查了资料,要改 putchar(),
找了一阵,没有找到 putchar ,估计是集成在某个地方,毕竟是标准化的.
随便找个位置 改了putchar,把输出定位到 uart1 上.
编译也成功了,到编译好的程序目录一看,乖乖,我这个程序什么没做就写了个hello word,  程序就占了5.XK.

这是难以容忍的~~

花了一上午的时间,自写了个函数,暂时能用,也没有纠错处理.

  1. int printf(u8 *fmt,...)
  2. {
  3.   u8 *strp;
  4.   s32 num;
  5.   u8 i=0,tmp=0;
  6.   
  7.   va_list args;
  8.   va_start ( args, fmt );
  9.   do
  10.   {
  11.     tmp = *(fmt+i) ;
  12.     if ( tmp != '%' )
  13.     {
  14.       UART1_SendByte( tmp );
  15.     }
  16.     else
  17.     {
  18.       i++;
  19.       tmp = *(fmt+i) ;
  20.       switch ( tmp )
  21.       {
  22.         case 'd':
  23.         case 'D':
  24.             num = va_arg( args, int );
  25.             UART1_SendNum( num );
  26.   //        UART1_PrintNum();
  27.           break;
  28.         case 's':
  29.         case 'S':
  30.           strp = va_arg( args,u8 *);
  31.           UART1_SendStr( strp );
  32.       }
  33.     }
  34.     i++;
  35.   } while( tmp != '\0' );

  36.   return 0;
  37. }
复制代码
使用类似标准库的 printf ,只是少了许多功能,我是感觉用处不大,也增加程序的难度,暂时凑合用着吧.
编译下, BIN文件仅仅 1.XK,很好.

当然一上午肯定不止写这么几行啦,还重写了 打数字函数,用来自动判断数字是 8位,16位,32位,有符号,无符号..至于浮点数,我比较少用,以后再研究了吧.


发表于 2016-2-22 17:49 | 显示全部楼层
sprintf函数自己先组合成字符串再串口送出去.
 楼主| 发表于 2016-2-22 18:07 | 显示全部楼层
桃之夭夭 发表于 2016-2-22 17:49
sprintf函数自己先组合成字符串再串口送出去.

嗯,是的.我没有说我的 printf 功能和 C标准库的一样.

我看了 printf 的原型,他首先开避了一个1KB的数组,用来放置 字符串.

我不需要这样做,实时发送就可以了.

发表于 2016-2-22 23:05 | 显示全部楼层
printf允许带数目可变的参数,并且参数的“类型”又是可变的,是最最复杂的C的函数,
看过Turbo C2.0的printf的源代码,是C和汇编语言混合编程,有16页纸长(都是小字体),估计编译出来至少得4K空间。
发表于 2016-2-22 23:20 | 显示全部楼层
我一般做法是,使用sprintf输出到一个缓冲区。
由于STM32的串口DMA发送本身就需要缓冲区,所以不多占用什么空间。
 楼主| 发表于 2016-2-23 09:39 | 显示全部楼层
locky_z 发表于 2016-2-22 23:05
printf允许带数目可变的参数,并且参数的“类型”又是可变的,是最最复杂的C的函数,
看过Turbo C2.0的pri ...

对,我这个 仿的 printf 参数也可变啊,参数类型也可变啊,除了第一个是 字符串/数组.

stm8 实测用 stdio.h ,编译后BIN文件5.X KB.
 楼主| 发表于 2016-2-23 09:40 | 显示全部楼层
Justinpiggy 发表于 2016-2-22 23:20
我一般做法是,使用sprintf输出到一个缓冲区。
由于STM32的串口DMA发送本身就需要缓冲区,所以不多占用什 ...

朋友,我用的是STM8 ,, ROM/RAM 本身就较紧张.


函数名取 printf , 是因为可以兼容某些程序,并没有说我的功能和原版一样.
发表于 2016-2-23 11:17 | 显示全部楼层
桃之夭夭 发表于 2016-2-22 17:49
sprintf函数自己先组合成字符串再串口送出去.

正解+1 喜欢这么刷屏
发表于 2016-2-24 00:39 | 显示全部楼层

rt_int32_t rt_vsnprintf(char       *buf,
                        rt_size_t   size,
                        const char *fmt,
                        va_list     args)
{
#ifdef RT_PRINTF_LONGLONG
    unsigned long long num;
#else
    rt_uint32_t num;
#endif
    int i, len;
    char *str, *end, c;
    const char *s;

    rt_uint8_t base;            /* the base of number */
    rt_uint8_t flags;           /* flags to print number */
    rt_uint8_t qualifier;       /* 'h', 'l', or 'L' for integer fields */
    rt_int32_t field_width;     /* width of output field */

#ifdef RT_PRINTF_PRECISION
    int precision;      /* min. # of digits for integers and max for a string */
#endif

    str = buf;
    end = buf + size - 1;

    /* Make sure end is always >= buf */
    if (end < buf)
    {
        end  = ((char *)-1);
        size = end - buf;
    }

    for (; *fmt ; ++fmt)
    {
        if (*fmt != '%')
        {
            if (str <= end)
                *str = *fmt;
            ++ str;
            continue;
        }

        /* process flags */
        flags = 0;

        while (1)
        {
            /* skips the first '%' also */
            ++ fmt;
            if (*fmt == '-') flags |= LEFT;
            else if (*fmt == '+') flags |= PLUS;
            else if (*fmt == ' ') flags |= SPACE;
            else if (*fmt == '#') flags |= SPECIAL;
            else if (*fmt == '0') flags |= ZEROPAD;
            else break;
        }

        /* get field width */
        field_width = -1;
        if (isdigit(*fmt)) field_width = skip_atoi(&fmt);
        else if (*fmt == '*')
        {
            ++ fmt;
            /* it's the next argument */
            field_width = va_arg(args, int);
            if (field_width < 0)
            {
                field_width = -field_width;
                flags |= LEFT;
            }
        }

#ifdef RT_PRINTF_PRECISION
        /* get the precision */
        precision = -1;
        if (*fmt == '.')
        {
            ++ fmt;
            if (isdigit(*fmt)) precision = skip_atoi(&fmt);
            else if (*fmt == '*')
            {
                ++ fmt;
                /* it's the next argument */
                precision = va_arg(args, int);
            }
            if (precision < 0) precision = 0;
        }
#endif
        /* get the conversion qualifier */
        qualifier = 0;
#ifdef RT_PRINTF_LONGLONG
        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
#else
        if (*fmt == 'h' || *fmt == 'l')
#endif
        {
            qualifier = *fmt;
            ++ fmt;
#ifdef RT_PRINTF_LONGLONG
            if (qualifier == 'l' && *fmt == 'l')
            {
                qualifier = 'L';
                ++ fmt;
            }
#endif
        }

        /* the default base */
        base = 10;

        switch (*fmt)
        {
        case 'c':
            if (!(flags & LEFT))
            {
                while (--field_width > 0)
                {
                    if (str <= end) *str = ' ';
                    ++ str;
                }
            }

            /* get character */
            c = (rt_uint8_t)va_arg(args, int);
            if (str <= end) *str = c;
            ++ str;

            /* put width */
            while (--field_width > 0)
            {
                if (str <= end) *str = ' ';
                ++ str;
            }
            continue;

        case 's':
            s = va_arg(args, char *);
            if (!s) s = "(NULL)";

            len = rt_strlen(s);
#ifdef RT_PRINTF_PRECISION
            if (precision > 0 && len > precision) len = precision;
#endif

            if (!(flags & LEFT))
            {
                while (len < field_width--)
                {
                    if (str <= end) *str = ' ';
                    ++ str;
                }
            }

            for (i = 0; i < len; ++i)
            {
                if (str <= end) *str = *s;
                ++ str;
                ++ s;
            }

            while (len < field_width--)
            {
                if (str <= end) *str = ' ';
                ++ str;
            }
            continue;

        case 'p':
            if (field_width == -1)
            {
                field_width = sizeof(void *) << 1;
                flags |= ZEROPAD;
            }
#ifdef RT_PRINTF_PRECISION
            str = print_number(str, end,
                               (long)va_arg(args, void *),
                               16, field_width, precision, flags);
#else
            str = print_number(str, end,
                               (long)va_arg(args, void *),
                               16, field_width, flags);
#endif
            continue;

        case '%':
            if (str <= end) *str = '%';
            ++ str;
            continue;

            /* integer number formats - set up the flags and "break" */
        case 'o':
            base = 8;
            break;

        case 'X':
            flags |= LARGE;
        case 'x':
            base = 16;
            break;

        case 'd':
        case 'i':
            flags |= SIGN;
        case 'u':
            break;

        default:
            if (str <= end) *str = '%';
            ++ str;

            if (*fmt)
            {
                if (str <= end) *str = *fmt;
                ++ str;
            }
            else
            {
                -- fmt;
            }
            continue;
        }

#ifdef RT_PRINTF_LONGLONG
        if (qualifier == 'L') num = va_arg(args, long long);
        else if (qualifier == 'l')
#else
        if (qualifier == 'l')
#endif
        {
            num = va_arg(args, rt_uint32_t);
            if (flags & SIGN) num = (rt_int32_t)num;
        }
        else if (qualifier == 'h')
        {
            num = (rt_uint16_t)va_arg(args, rt_int32_t);
            if (flags & SIGN) num = (rt_int16_t)num;
        }
        else
        {
            num = va_arg(args, rt_uint32_t);
            if (flags & SIGN) num = (rt_int32_t)num;
        }
#ifdef RT_PRINTF_PRECISION
        str = print_number(str, end, num, base, field_width, precision, flags);
#else
        str = print_number(str, end, num, base, field_width, flags);
#endif
    }

    if (str <= end) *str = '\0';
    else *end = '\0';

    /* the trailing null byte doesn't count towards the total
    * ++str;
    */
    return str - buf;
}
RTM_EXPORT(rt_vsnprintf);


这个是RT thread里面的~可以参考

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-5-19 18:12 , Processed in 0.070659 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表