标题: 精减版本Printf函数 适合小容量MCU [打印本页]

作者: wxmlx    时间: 2021-10-17 18:07
标题: 精减版本Printf函数 适合小容量MCU
单片机源程序如下:
  1. #include <stdarg.h>
  2. //名称:适用于mega8等小容量MCU的sprintf函数//
  3. //简介:主要针对小容量MCU flash ram有限,使用标准springf函数占用空间过大,莫名堆栈溢出问题//
  4. //函数仅支持16位无符号整形和字符串的转换,如果要转换float型,请使用//
  5. //额外提供的 将float转换为字符串的函数//


  6. void sprintfx(char * str,flash char * fmtstr,...)
  7. {
  8.         va_list argptr;
  9.         char * cp;
  10.         unsigned char k,loop=0,loopstr=0,loops,active;
  11.         unsigned int utmp,m;
  12.         va_start(argptr,fmtstr);
  13.         while (fmtstr[loop])
  14.         {
  15.                 k=fmtstr[loop];
  16.                 if(k!='%')
  17.                 {
  18.                         str[loopstr]=k;
  19.                         loopstr++;
  20.                 }
  21.                 else
  22.                 {
  23.                         loop++;                //指向%号的下一个字符,确定变量类型//
  24.                         k=fmtstr[loop];
  25.                         switch(k)
  26.                         {
  27.                                 case 'u':
  28.                                         utmp=*(unsigned int*)(argptr);
  29.                                         va_arg(argptr,int);
  30.                                         if(utmp==0)
  31.                                         {
  32.                                                 str[loopstr]=0x30;
  33.                                                 loopstr++;
  34.                                                 break;
  35.                                         }
  36.                                         m=10000;
  37.                                         active=0;        //暂无有效位//
  38.                                         for(loops=0;loops<5;loops++)        //unsigned int 最大65535 占5位//
  39.                                         {
  40.                                                 if(utmp>=m)
  41.                                                 {
  42.                                                         active=1;        //得到有效位//
  43.                                                 }
  44.                                                 if(active)
  45.                                                 {
  46.                                                         str[loopstr]=(unsigned char)(utmp/m)+0x30;
  47.                                                         loopstr++;
  48.                                                         utmp=utmp%m;
  49.                                                 }
  50.                                                 m=m/10;
  51.                                         }
  52.                                 break;
  53.                                 
  54.                                 case 's':
  55.                                         utmp=*((unsigned int *)(argptr));
  56.                                         cp=(char *)(utmp);
  57.                                         va_arg(argptr,char *);        
  58.                                         loops=0;
  59.                                         while(cp[loops])
  60.                                         {
  61.                                                 str[loopstr]=cp[loops];
  62.                                                 loops++;
  63.                                                 loopstr++;
  64.                                         }
  65.                                 break;

  66.                                 default:
  67.                                 break;
  68.                         };
  69.                         
  70.                 }
  71.                 loop++;
  72.         };
  73.         str[loopstr]=0;
  74.         va_end(argptr);
  75. }


  76. //将float转换为字符串//
  77. //用法:fdat待转换的float变量、maxlen最大转换完的长度(包含小数点及其小数)取值最大不要超过16//
  78. //pre小数点后保留的位数取值不要超过4、xbuf转换结果存放的缓冲区//
  79. //注意:float的整数部分只支持到65535。程序没有对各个变量的取值进行合理性判别//
  80. void sprintf_float(float fdat,unsigned char maxlen,unsigned char pre,char *xbuf)
  81. {
  82.         char buf[18];
  83.         unsigned char loop=11,startpos,len;        //循环变量、开始位置、长度//
  84.         unsigned char sn=0;                        //数值的正负 兼顾endpos//
  85.         unsigned int lint;                        //整数部分//

  86.         //最大转换长度18个//
  87.         if(maxlen>18)
  88.         {
  89.                 return;
  90.         }
  91.         ///////////////////小数点前的部分//////////////////////////
  92.         if(fdat<0)
  93.         {
  94.                 sn=1;
  95.                 fdat=0-fdat;
  96.         }
  97.         lint=(unsigned int)(fdat);
  98.         while(loop)
  99.         {
  100.                 buf[loop]=lint%10+0x30;
  101.                 lint=lint/10;
  102.                 loop--;
  103.                 if(lint==0)
  104.                 {
  105.                         break;
  106.                 }
  107.         }
  108.         if(sn==1)
  109.         {
  110.                 buf[loop]='-';
  111.         }
  112.         else
  113.         {
  114.                 loop++;
  115.         }
  116.         startpos=loop;
  117.         len=12-startpos;//整数部分长度//
  118.         if(len>=maxlen)        //如果整数位(包括负号)长度已经大于限定长度,强制添0//
  119.         {
  120.                 buf[(unsigned char)(startpos+maxlen)]=0;
  121.                 sn=startpos+maxlen;
  122.         }
  123.         else
  124.         {
  125.                 if((maxlen-len)>=2)
  126.                 {
  127.                         buf[12]='.';
  128.                         //////////////////分解小数部分////////////////////////
  129.                         len=maxlen-len-1;        //小数点后长度//
  130.                         if(pre<len)                //如果精度要求低于剩余长度,按照精度要求计算//
  131.                         {
  132.                                 len=pre;
  133.                         }
  134.                         lint=(unsigned int)(fdat);
  135.                         fdat=fdat-(float)(lint);
  136.                         for(loop=13;loop<(13+len);loop++)
  137.                         {
  138.                                 fdat=fdat*10;
  139.                                 lint=((unsigned int)(fdat));
  140.                                 fdat=fdat-(float)(lint);
  141.                                 buf[loop]=(char)(lint)+0x30;
  142.                         }
  143.                         while(loop<(startpos+maxlen))
  144.                         {
  145.                                 buf[loop]=' ';
  146.                                 loop++;
  147.                         }
  148.                         buf[loop]=0;
  149.                         sn=loop;
  150.                 }
  151.                 else
  152.                 {
  153.                         buf[12]=' ';
  154.                         buf[13]=0;
  155.                         sn=13;
  156.                 }
  157.         }
  158.         //////////////////基0搬移数据//////////////////////
  159.         for(loop=0;loop<=(sn-startpos);loop++)
  160.         {
  161.                 xbuf[loop]=buf[startpos+loop];
  162.         }
  163. }





  164. //用法示例程序//
  165. /*
  166. char buf[64];
  167. int  adr=60035;
  168. char s1[]="12";
  169. char s2[]="456789";
  170. char s3[10];
  171. float fv=1513.28;

  172. void main(void)
  173. {
  174.         sprintf_float(fv,8,2,s3);
  175.         sprintfx(buf,"adr=%u s1=%s s2=%s fv=%s",adr,s1,s2,s3);
  176.         while(1)
  177.         {
  178.         
  179.         }
  180. }

  181. */
复制代码


以上4个文件下载:
精减版本printf.rar (2.49 KB, 下载次数: 21)






欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1